Reusable Python Code Modules, Part 2 - Request Validation
Ensuring Data Integrity: Building Robust Request Validation Modules
Request validation ensures that incoming data meets specific criteria before processing. Proper validation helps prevent errors, enhances security, and improves data integrity. This guide covers how to structure reusable request validation modules in Python, manage validations efficiently, and integrate common libraries.
Common Libraries and Tools
1. Pydantic
Pydantic is a data validation and settings management library using Python type annotations
Key Features
Data parsing and validation using Python type hints
Built-in support for complex data types
Custom error messages
Integration with FastAPI
2. Marshmallow
Marshmallow is an ORM/ODM/framework-agnostic library for data serialization, deserialization, and validation.
Key Features
Schema-based validation
Serialization and deserialization
Custom validators and error messages
Integration with various ORMs
3. Cerberus
Cerberus is a lightweight and extensible data validation library for Python
Key Features
Simple schema definition
Built-in and custom validation rules
Extensible with custom validators
Integration with various frameworks
4. Voluptuous
Voluptuous is a Python library for validating data against a schema
Key Features
Simple and expressive schema definition
Built-in and custom validation rules
Error handling and custom error messages
Integration with various frameworks
Comparison
Pydantic: Best for applications needing type-based validation and complex data type support
Marshmallow: Ideal for schema-based validation with serialization and deserialization capabilities
Cerberus: Suitable for lightweight validation needs with simple schema definitions
Voluptuous: Best for expressive schema definitions and custom validation rules
Examples
Example 1: Pydantic
Setup:
$ pip install pydantic
Schema Definition:
from pydantic import BaseModel, EmailStr, validator
class User(BaseModel):
name: str
email: EmailStr
password: str
@validator('password')
def password_length(cls, v):
if len(v) < 6:
raise ValueError('Password must be at least 6 characters long')
return v
Usage:
from fastapi import FastAPI, HTTPException
from pydantic import ValidationError
app = FastAPI()
@app.post('/register')
async def register(user: User):
try:
user = User(**user.dict())
return {"message": "User registered successfully"}
except ValidationError as e:
raise HTTPException(status_code=400, detail=e.errors())
Example 2: Marshmallow
Setup:
$ pip install marshmallow
Schema Definition:
from marshmallow import Schema, fields, validates, ValidationError
class UserSchema(Schema):
name = fields.Str(required=True)
email = fields.Email(required=True)
password = fields.Str(required=True)
@validates('password')
def validate_password(self, value):
if len(value) < 6:
raise ValidationError('Password must be at least 6 characters long')
Usage:
from flask import Flask, request, jsonify
from marshmallow import ValidationError
from your_schemas import UserSchema
app = Flask(__name__)
user_schema = UserSchema()
@app.route('/register', methods=['POST'])
def register():
try:
user = user_schema.load(request.json)
return jsonify({"message": "User registered successfully"})
except ValidationError as err:
return jsonify(err.messages), 400
if __name__ == '__main__':
app.run(debug=True)
Example 3: Cerberus
Setup:
$ pip install cerberus
Schema Definition:
from cerberus import Validator
user_schema = {
'name': {'type': 'string', 'required': True},
'email': {'type': 'string', 'regex': r'^\S+@\S+\.\S+$', 'required': True},
'password': {'type': 'string', 'minlength': 6, 'required': True},
}
v = Validator(user_schema)
Usage:
from flask import Flask, request, jsonify
from your_validator import v
app = Flask(__name__)
@app.route('/register', methods=['POST'])
def register():
if not v.validate(request.json):
return jsonify(v.errors), 400
return jsonify({"message": "User registered successfully"})
if __name__ == '__main__':
app.run(debug=True)
Example 4: Voluptuous
Setup:
$ pip install voluptuous
Schema Definition:
from voluptuous import Schema, Required, Email, Length
user_schema = Schema({
Required('name'): str,
Required('email'): Email(),
Required('password'): Length(min=6)
})
Usage:
from flask import Flask, request, jsonify
from voluptuous import Invalid
from your_schemas import user_schema
app = Flask(__name__)
@app.route('/register', methods=['POST'])
def register():
try:
user_schema(request.json)
return jsonify({"message": "User registered successfully"})
except Invalid as e:
return jsonify({"error": str(e)}), 400
if __name__ == '__main__':
app.run(debug=True)