Automatic Pydantic validation and ReDoc documentation generation for Flask endpoints
Project description
flask-redantic
Automatic Pydantic validation and ReDoc API documentation for Flask — annotation-driven.
redantic is a lightweight Flask library that:
- Validates request bodies and query parameters by reading your type annotations
- Injects validated Pydantic model instances directly into your view functions
- Auto-generates interactive ReDoc API documentation - no YAML, no manual schema config
- Requires zero boilerplate - your annotations and docstrings are the source of truth
Installation
uv add flask-redantic
Quick Start
from flask import Flask, jsonify
from pydantic import BaseModel, Field
from redantic import Redantic
from redantic.raises import HTTP_404, HTTP_422
app = Flask(__name__)
api = Redantic(title="Quark's Bar API", version="v1.0")
class ItemIn(BaseModel):
name: str = Field(..., min_length=1)
category: str
price_slips: int = Field(..., ge=0)
class ItemOut(BaseModel):
id: int
name: str
category: str
price_slips: int
class ErrorOut(BaseModel):
message: str
@app.post("/inventory")
@api.validate(
tags=["inventory"],
raises=[HTTP_422()],
success_status=201,
)
def create_item(body: ItemIn) -> ItemOut:
"""
Acquire new stock for Quark's.
The body is validated and injected automatically.
"""
return jsonify({"id": 1, **body.model_dump()}), 201
@app.get("/inventory/<int:item_id>")
@api.validate(tags=["inventory"], raises=[HTTP_404(ErrorOut)])
def get_item(item_id: int) -> ItemOut:
"""Retrieve an item by ID."""
item = db.get(item_id)
if not item:
return jsonify({"message": "Not found"}), 404
return jsonify(item)
api.init_app(app)
Visit:
http://localhost:5000/docs→ Interactive ReDoc documentationhttp://localhost:5000/docs/openapi.json→ Raw OpenAPI 3.0 JSON spec
How It Works
Everything is driven by standard Python type annotations:
| Annotation | Effect |
|---|---|
body: MyModel |
JSON body validated → body is a MyModel instance |
query: MyModel |
Query-string params validated → query is a MyModel instance |
item_id: int (Flask path param) |
Passed through unchanged by Flask |
-> MyModel |
Documents the success response schema |
raises=[HTTP_404(ErrorOut)] |
Documents error response schemas |
Body injection
@app.post("/inventory")
@api.validate(tags=["inventory"], success_status=201)
def create_item(body: ItemIn) -> ItemOut:
# `body` is a fully validated ItemIn instance — ready to use
return jsonify({"id": 1, **body.model_dump()}), 201
Body + path parameter
Flask path parameters are passed normally; redantic injects body/query alongside them:
@app.put("/inventory/<int:item_id>")
@api.validate(tags=["inventory"], raises=[HTTP_404(ErrorOut)])
def update_item(item_id: int, body: ItemIn) -> ItemOut:
# item_id comes from Flask routing
# body is injected by redantic
...
Query parameters
Use a parameter named query annotated with a BaseModel:
class ItemFilter(BaseModel):
category: str | None = None
max_price: int | None = Field(None, ge=0)
@app.get("/inventory")
@api.validate(tags=["inventory"])
def list_items(query: ItemFilter) -> ItemOut:
if query.category:
...
@api.validate Parameters
| Parameter | Type | Description |
|---|---|---|
raises |
list[RaisesSpec] |
Error response declarations (see below) |
tags |
list[str] |
Group endpoints in the ReDoc sidebar |
summary |
str | None |
One-line description. Auto-detected from first docstring line if omitted |
deprecated |
bool |
Mark endpoint as deprecated in docs |
success_status |
int |
Success HTTP status code (default: 200). Override to 201 for creation endpoints |
Validation errors
When a request body or query fails validation, redantic automatically returns:
HTTP 422 Unprocessable Entity
{
"detail": [
{
"loc": ["name"],
"msg": "String should have at least 1 character",
"type": "string_too_short"
}
]
}
raises — Declaring Error Responses
Import the pre-built HTTP error helpers from redantic.raises:
from redantic.raises import HTTP_400, HTTP_401, HTTP_403, HTTP_404, HTTP_409, HTTP_422, HTTP_500
@api.validate(raises=[
HTTP_404(ErrorOut), # 404 with ErrorOut schema
HTTP_403(), # 403 with no body
HTTP_422, # 422 with no body (no parentheses needed)
])
def my_endpoint(...): ...
Available helpers: HTTP_400, HTTP_401, HTTP_403, HTTP_404, HTTP_409, HTTP_422, HTTP_429, HTTP_500, HTTP_503
Note: A 422 Unprocessable Entity response is automatically added to the spec whenever a body or query model is present. You don't need to add it manually.
Application Factory Pattern
from redantic import Redantic
api = Redantic(
title="My API",
version="v1.0",
description="Supports **Markdown** in the overview section.",
path="doc", # /docs UI, /docs/openapi.json spec
)
from extensions import api
from flask import Flask
def create_app():
app = Flask(__name__)
# ... register routes ...
api.init_app(app) # call AFTER all routes are registered
return app
Redantic Configuration
api = Redantic(
app, # optional Flask app; pass later via init_app()
title="My API", # shown in ReDoc header
version="v2.0", # shown in ReDoc version badge
description="...", # Markdown shown in ReDoc overview
path="doc", # URL prefix; /docs UI, /docs/openapi.json spec
)
Running the Example
pip install -e .
python examples/app.py
# → http://localhost:5050/docs
Project Structure
flask-redantic/
├── src/redantic/
│ ├── __init__.py # Public API: Redantic
│ ├── core.py # Redantic class + Flask Blueprint
│ ├── decorator.py # @validate decorator + signature inspection
│ ├── spec.py # OpenAPI 3.0 spec builder
│ ├── raises.py # HTTP_xxx error-response helpers
│ └── templates.py # ReDoc HTML template
└── examples/
└── app.py # Runnable Quark's Bar demo
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flask_redantic-0.1.0.tar.gz.
File metadata
- Download URL: flask_redantic-0.1.0.tar.gz
- Upload date:
- Size: 65.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
48bcded68a1c44a9ca63a596809b8f688a186b1db92c51fe45df3e64b358cdea
|
|
| MD5 |
62332be50a3c16cd3905cb3fd5e8e7ac
|
|
| BLAKE2b-256 |
2067eff7523581247bac6e1f6deb75eda39b012a1fed3ec5eafae35ced3c6eb1
|
Provenance
The following attestation bundles were made for flask_redantic-0.1.0.tar.gz:
Publisher:
publish.yml on wagnercder/flask-redantic
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
flask_redantic-0.1.0.tar.gz -
Subject digest:
48bcded68a1c44a9ca63a596809b8f688a186b1db92c51fe45df3e64b358cdea - Sigstore transparency entry: 1629923036
- Sigstore integration time:
-
Permalink:
wagnercder/flask-redantic@54790ff045d1ee0e52efd6b59ca4ccb01bcd1397 -
Branch / Tag:
refs/tags/v0.1 - Owner: https://github.com/wagnercder
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@54790ff045d1ee0e52efd6b59ca4ccb01bcd1397 -
Trigger Event:
release
-
Statement type:
File details
Details for the file flask_redantic-0.1.0-py3-none-any.whl.
File metadata
- Download URL: flask_redantic-0.1.0-py3-none-any.whl
- Upload date:
- Size: 12.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
acf84d295d5546f14de40cb2bbfb61fb9d6ae8f84596268d2a823d1e068216ac
|
|
| MD5 |
cc869c58bb7ba05df1816b8c7c59f900
|
|
| BLAKE2b-256 |
84bdd110dfc5ba897fbf8d14225c45194e66d5b57b2f58700eb735c34387525c
|
Provenance
The following attestation bundles were made for flask_redantic-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on wagnercder/flask-redantic
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
flask_redantic-0.1.0-py3-none-any.whl -
Subject digest:
acf84d295d5546f14de40cb2bbfb61fb9d6ae8f84596268d2a823d1e068216ac - Sigstore transparency entry: 1629923059
- Sigstore integration time:
-
Permalink:
wagnercder/flask-redantic@54790ff045d1ee0e52efd6b59ca4ccb01bcd1397 -
Branch / Tag:
refs/tags/v0.1 - Owner: https://github.com/wagnercder
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@54790ff045d1ee0e52efd6b59ca4ccb01bcd1397 -
Trigger Event:
release
-
Statement type: