flask_typed_routes is a Flask
extension designed to effortlessly validate requests with Pydantic
based on standard Python type hints.
Documentation: https://rmoralespp.github.io/flask_typed_routes/
- Easy: Easy to use and integrate with Flask applications.
- Standard-based: Based on OpenAPI Specification
- Data validation: Fast data verification based on Pydantic
- Python 3.10+
- Pydantic 2.0+
- Flask
To install flask_typed_routes using pip
, run the following command:
pip install flask_typed_routes
This tool allows you to validate request parameters in Flask, similar to how FastAPI handles validation. It supports Path, Query, Header, Cookie, and Body validation.
Create a file items.py
with:
import flask
import flask_typed_routes as ftr
app = flask.Flask(__name__)
ftr.FlaskTypedRoutes(app=app)
@app.get("/")
def read_root():
return flask.jsonify({"Hello": "World"})
@app.get("/items/<user>/")
def read_items(user: str, skip: int = 0, limit: int = 10):
return flask.jsonify({"user": user, "skip": skip, "limit": limit})
Run the server with:
flask --app items run --debug
Open your browser and go to http://127.0.0.1:5000/items/myuser/?skip=20
You will see the JSON response as:
{
"limit": 10,
"skip": 20,
"user": "myuser"
}
Validation: Open your browser and go to http://127.0.0.1:5000/items/myuser/?skip=abc
You will see the JSON response with the error details because the skip
parameter is not an integer:
{
"errors": [
{
"input": "abc",
"loc": [
"query",
"skip"
],
"msg": "Input should be a valid integer, unable to parse string as an integer",
"type": "int_parsing",
"url": "https://errors.pydantic.dev/2.9/v/int_parsing"
}
]
}
You can also use Pydantic models to validate the request body.
Now let's update the items.py
file with:
import flask
import flask_typed_routes as ftr
import pydantic
app = flask.Flask(__name__)
ftr.FlaskTypedRoutes(app=app)
class Item(pydantic.BaseModel):
name: str
price: float
description: str = None
@app.get("/")
def read_root():
return flask.jsonify({"Hello": "World"})
@app.get("/items/<user>/")
def read_items(user: str, skip: int = 0, limit: int = 10):
return flask.jsonify({"user": user, "skip": skip, "limit": limit})
@app.post('/items/')
def create_item(item: Item):
return flask.jsonify(item.model_dump())
@app.put('/items/<item_id>/')
def update_item(item_id: int, item: Item):
return flask.jsonify({'item_id': item_id, **item.model_dump()})
Now let's update the items.py
file with:
import flask
import flask_typed_routes as ftr
app = flask.Flask(__name__)
ftr.FlaskTypedRoutes(app=app)
orders = flask.Blueprint('orders', __name__)
@orders.get("/orders/<user>/")
def read_orders(user: str, skip: int = 0, limit: int = 10):
return flask.jsonify({"user": user, "skip": skip, "limit": limit})
app.register_blueprint(orders)
Now let's update the items.py
file with:
import flask
import flask.views
import flask_typed_routes as ftr
app = flask.Flask(__name__)
ftr.FlaskTypedRoutes(app=app)
class UserProducts(flask.views.View):
def dispatch_request(self, user: str, skip: int = 0, limit: int = 10):
data = {'user': user, 'skip': skip, 'limit': limit}
return flask.jsonify(data)
class UserOrders(flask.views.MethodView):
def get(self, user: str, skip: int = 0, limit: int = 10):
data = {'user': user, 'skip': skip, 'limit': limit}
return flask.jsonify(data)
app.add_url_rule('/products/<user>/', view_func=UserProducts.as_view('user_products'))
app.add_url_rule('/orders/<user>/', view_func=UserOrders.as_view('user_orders'))
You can generate interactive API docs for your Flask application using OpenAPI schema generated by flask_typed_routes
with any OpenAPI UI library. For example, you can use swagger-ui-py
to generate the API docs.
pip install swagger-ui-py # ignore if already installed
import flask
import flask_typed_routes as ftr
import pydantic
import swagger_ui
app = flask.Flask(__name__)
app_ftr = ftr.FlaskTypedRoutes(app=app)
class Item(pydantic.BaseModel):
name: str
price: float
description: str = None
@app.get('/items/<user>/')
def read_items(user: str, skip: int = 0, limit: int = 10):
data = {'user': user, 'skip': skip, 'limit': limit}
return flask.jsonify(data)
@app.post('/items/')
def create_item(item: Item):
return flask.jsonify(item.model_dump())
@app.put('/items/<item_id>/')
def update_item(item_id: int, item: Item):
return flask.jsonify({'item_id': item_id, **item.model_dump()})
@app.delete('/items/<item_id>/')
def remove_item(item_id: int):
return flask.jsonify({'item_id': item_id})
swagger_ui.api_doc(app, config=app_ftr.get_openapi_schema(), url_prefix='/docs')
Open your browser and go to http://127.0.0.1:5000/docs/
Create item endpoint:
Read Items endpoint:
For more detailed information and usage examples, refer to the project documentation
To contribute to the project, you can run the following commands for testing and documentation:
Install the development dependencies and run the tests:
(env)$ pip install -r requirements-dev.txt # Skip if already installed
(env)$ python -m pytest tests/
(env)$ python -m pytest --cov # Run tests with coverage
To build the documentation locally, use the following commands:
(env)$ pip install -r requirements-doc.txt # Skip if already installed
(env)$ mkdocs serve # Start live-reloading docs server
(env)$ mkdocs build # Build the documentation site
This project is licensed under the MIT license.