Flask-Pydantic
Flask-Pydantic is a Flask extension that integrates the Pydantic library for robust data validation and serialization. It streamlines the process of validating incoming request data (query parameters, JSON bodies, form data, and path parameters) and serializing outgoing responses using Pydantic models, enhancing type safety and developer experience in Flask applications. The current version is 0.14.0, and it is actively maintained as part of the Pallets Community Ecosystem, with regular releases addressing new features and bug fixes.
Warnings
- breaking When migrating to Pydantic V2, direct usage of Pydantic V1 methods (e.g., `.dict()`, `.json()`, `.parse_obj()`) on your Pydantic models will break. Flask-Pydantic (from v0.13.0) supports both Pydantic V1 and V2, but your application code must be updated.
- gotcha The order of decorators matters. The `@app.route` decorator must always precede the `@validate()` decorator (i.e., `@validate()` should be closer to the function definition). Incorrect order will lead to validation not being applied.
- gotcha Prior to version 0.13.2, `flask-pydantic` did not fully support asynchronous Flask views. Using `@validate` on `async def` routes might have led to unexpected behavior or errors.
- gotcha Path parameter validation with dependency injection was fixed in version 0.14.0. Users on older versions might encounter issues where path parameters are not correctly validated or injected when used alongside other dependencies.
- gotcha By default, `flask-pydantic` returns a 400 HTTP status code with a JSON error message upon validation failure. If you need custom error responses (e.g., a different status code, error format, or to raise a specific exception), the default behavior needs to be overridden.
Install
-
pip install Flask-Pydantic
Imports
- validate
from flask_pydantic import validate
- BaseModel
from pydantic import BaseModel
- Flask
from flask import Flask
Quickstart
from typing import Optional
from flask import Flask, request, jsonify
from pydantic import BaseModel, Field
from flask_pydantic import validate
app = Flask(__name__)
class QueryModel(BaseModel):
age: int = Field(..., ge=0, description="User's age")
city: Optional[str] = None
class RequestBodyModel(BaseModel):
name: str = Field(..., min_length=2, max_length=50)
email: str = Field(..., pattern="^.+@.+\..+$") # Simple email regex
class ResponseModel(BaseModel):
message: str
user_info: dict
@app.route("/users", methods=["GET"])
@validate(query=QueryModel)
def get_user_info(query: QueryModel):
"""Get user info based on query parameters."""
return jsonify(ResponseModel(
message="User info retrieved successfully",
user_info={"age": query.age, "city": query.city}
).model_dump())
@app.route("/users", methods=["POST"])
@validate(body=RequestBodyModel)
def create_user(body: RequestBodyModel):
"""Create a new user with validated request body."""
# In a real app, you would save `body` to a database
return jsonify(ResponseModel(
message=f"User {body.name} created with email {body.email}",
user_info=body.model_dump()
).model_dump()), 201
if __name__ == "__main__":
# Example usage: start server and make requests like:
# GET /users?age=30&city=NewYork
# POST /users with JSON body: {"name": "Alice", "email": "alice@example.com"}
app.run(debug=True, port=5000)