Flask extension for integration of the awesome pydantic package with Flask.
python3 -m pip install Flask-Pydantic
validate decorator validates query and body request parameters and makes them accessible two ways:
| parameter type | request attribute name |
|---|---|
| query | query_params |
| body | body_params |
- Success response status code can be modified via
on_success_statusparameter ofvalidatedecorator. response_manyparameter set toTrueenables serialization of multiple models (route function should therefore return iterable of models).request_body_manyparameter set toFalseanalogically enables serialization of multiple models inside of the root level of request body. If the request body doesn't contain an array of objects400response is returned,- If validation fails,
400response is returned with failure explanation.
For more details see in-code docstring or example app.
Simply use validate decorator on route function.
❗ Be aware that @app.route decorator must precede @validate (i. e. @validate must be closer to the function declaration).
from typing import Optional
from flask import Flask, request
from flask_pydantic import validate
from pydantic import BaseModel
app = Flask("flask_pydantic_app")
class QueryModel(BaseModel):
age: int
class BodyModel(BaseModel):
name: str
nickname: Optional[str]
class ResponseModel(BaseModel):
id: int
age: int
name: str
nickname: Optional[str]
@app.route("/", methods=["POST"])
@validate(body=BodyModel, query=QueryModel)
def post():
# save model to DB
id_ = ...
return ResponseModel(
id=id_,
age=request.query_params.age,
name=request.body_params.name,
nickname=request.body_params.nickname,
)agequery parameter is a requiredint- if none is provided the response contains:
{ "validation_error": { "query_params": [ { "loc": ["age"], "msg": "field required", "type": "value_error.missing" } ] } } - for incompatible type (e. g. string
/?age=not_a_number){ "validation_error": { "query_params": [ { "loc": ["age"], "msg": "value is not a valid integer", "type": "type_error.integer" } ] } }
- if none is provided the response contains:
- likewise for body parameters
- example call with valid parameters:
curl -XPOST http://localhost:5000/?age=20 --data '{"name": "John Doe"}' -H 'Content-Type: application/json'
-> {"id": 2, "age": 20, "name": "John Doe", "nickname": null}
The default success status code is 200. It can be modified in two ways
- in return statement
# necessary imports, app and models definition
...
@app.route("/", methods=["POST"])
@validate(body=BodyModel, query=QueryModel)
def post():
return ResponseModel(
id=id_,
age=request.query_params.age,
name=request.body_params.name,
nickname=request.body_params.nickname,
), 201- in
validatedecorator
@app.route("/", methods=["POST"])
@validate(body=BodyModel, query=QueryModel, on_success_status=201)
def post():
...Status code in case of validation error can be modified using FLASK_PYDANTIC_VALIDATION_ERROR_STATUS_CODE flask configuration variable.
Instead of passing body and query to validate, it is possible to directly
defined them by using type hinting in the decorated function.
# necessary imports, app and models definition
...
@app.route("/", methods=["POST"])
@validate()
def post(body: BodyModel, query: QueryModel):
return ResponseModel(
id=id_,
age=query.age,
name=body.name,
nickname=body.nickname,
)This way, the parsed data will be directly available in body and query.
Furthermore, your IDE will be able to correctly type them.
Pydantic's alias feature is natively supported for query and body models. To use aliases in response modify response model
def modify_key(text: str) -> str:
# do whatever you want with model keys
return text
class MyModel(BaseModel):
...
class Config:
alias_generator = modify_key
allow_population_by_field_name = Trueand set response_by_alias=True in validate decorator
@app.route(...)
@validate(response_by_alias=True)
def my_route():
...
return MyModel(...)
For more complete examples see example application.
The behaviour can be configured using flask's application config
FLASK_PYDANTIC_VALIDATION_ERROR_STATUS_CODE - response status code after validation error (defaults to 400)
Feature requests and pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
- clone repository
git clone https://github.com/bauerji/flask_pydantic.git cd flask_pydantic - create virtual environment and activate it
python3 -m venv venv source venv/bin/activate - install development requirements
python3 -m pip install -r requirements/test.pip
- checkout new branch and make your desired changes (don't forget to update tests)
git checkout -b <your_branch_name>
- run tests
python3 -m pytest
- if tests fails on Black tests, make sure You have your code compliant with style of Black formatter
- push your changes and create a pull request to master branch
- header request parameters
- cookie request parameters