A production-grade FastAPI application demonstrating every advanced Pydantic v2 feature.
# 1. Clone & setup
git clone <your-repo-url>
cd pydantic-mastery
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
# 2. Install dependencies
pip install -r requirements.txt
# 3. Run server
uvicorn app.main:app --reload --host 127.0.0.1 --port 8000
# 4. Open interactive docs
open http://127.0.0.1:8000/docs # Mac
start http://127.0.0.1:8000/docs # Windowspydantic-mastery/
โโโ README.md # You are here
โโโ requirements.txt # Python dependencies
โโโ app/
โ โโโ main.py # FastAPI entrypoint, middleware, wiring
โ โโโ core/
โ โ โโโ config.py # Pydantic Settings, env overrides, SecretStr
โ โ โโโ exceptions.py # Structured error handlers, request ID tracing
โ โโโ middleware/
โ โ โโโ request_id.py # Async middleware for correlation IDs
โ โโโ models/ # 11 focused Pydantic v2 feature files
โ โโโ routes/
โ โ โโโ pydantic_lab.py # 50+ learning & playground endpoints
โ โโโ services/ # Optional: typed JSON storage (future)
โ โโโ data/
โ โโโ data.json # Production-like test records
โ โโโ playground_examples.json # Valid/invalid payloads for UI
โโโ tests/ # pytest suite: models, routes, middleware
โโโ docs/ # (Optional) Static documentation output
| Feature | File | Real-World Use Case |
|---|---|---|
BaseModel & Field() constraints |
basics.py |
API contracts, form validation |
@field_validator(mode="before/after/wrap") |
field_validators.py |
Email normalization, tag dedup, age rules |
@model_validator(mode="before/after") |
model_validators.py |
Password matching, cross-field business logic |
@computed_field |
computed.py |
Derived values, pricing breakdowns, status badges |
TypeAdapter |
type_adapters.py |
Webhook validation, config files, batch imports |
ConfigDict (strict, extra, aliases, frozen) |
strict_config.py |
Input hardening, JS/Python naming sync, immutability |
StrEnum, EmailStr, SecretStr, HttpUrl |
enum_custom.py |
Role-based access, secure token handling, URL validation |
@field_serializer, include/exclude, context |
serialization.py |
Public vs admin payloads, ORM sync, frontend optimization |
Annotated[T, ...] pipelines |
annotated_advanced.py |
Reusable domain types, composable constraint chains |
Recursive models & Generic[T] |
nested_generics.py |
Comment threads, org trees, paginated API responses |
Field(discriminator="...") unions |
discriminated_unions.py |
Payment methods, webhook routing, search filters |
The /lab/playground/* endpoints are explicitly designed to power a future React/Vue frontend:
| Endpoint | Purpose | Frontend Integration |
|---|---|---|
POST /lab/playground/validate?model=... |
Universal validator: any model + payload | Live validation with field_errors for inline editor highlighting |
GET /lab/playground/schema/{model} |
Export OpenAPI-compatible JSON Schema | Auto-generate TypeScript interfaces & dynamic forms |
GET /lab/playground/examples/{model} |
Return valid/invalid example payloads | "Try It" buttons with pre-filled test cases |
POST /lab/playground/compare |
Side-by-side validation (strict vs lenient) | Visual comparison of config impact on validation behavior |
Example Playground Flow:
- User selects a model โ fetches examples from
/playground/examples/{model} - Edits JSON in a Monaco editor โ submits to
/playground/validate - API returns structured errors with
field_errorskeys โ frontend highlights invalid fields - Success response includes computed fields & updated schema
# Run full test suite
pytest tests/ -v
# Run with coverage report
pytest tests/ --cov=app/models --cov-report=term-missing
# Watch mode for TDD
pip install pytest-watch
ptwTest Coverage:
- โ Unit validation (constraints, validator modes, computed fields)
- โ Discriminator union routing & batch validation
- โ Structured error formatting & request ID propagation
- โ Endpoint integration & schema export
- โ Middleware request ID generation/passthrough
| Layer | Tool | Purpose |
|---|---|---|
| Framework | FastAPI 0.115+ | Async routing, auto OpenAPI, dependency injection |
| Validation | Pydantic 2.x | Type-safe models, modern validators, JSON schema |
| Config | pydantic-settings |
Env loading, secret masking, environment overrides |
| Testing | pytest + httpx |
Async test client, validation assertions |
| Docs | Swagger UI / ReDoc | Interactive API explorer, try-it payloads |
This project demonstrates expert-level Pydantic v2 mastery with production-ready patterns:
- Strict Validation Pipelines:
mode="before/after/wrap"replaces fragile legacy validators - Composable Constraints:
Annotated[T, metadata]creates reusable, DRY validation rules - Type-Safe Routing:
Field(discriminator=...)replacesif/elsewith auto-validated unions - Structured Errors: Frontend-ready
field_errorsmapping with contextual tips - Context-Aware Serialization: One model โ public API / admin view / frontend payload
- Runtime Validation:
TypeAdapterhandles webhook/plugin configs without static models
How to see demo:
- Open
/docsโ click "Try it out" on any endpoint - Show
/lab/playground/compareto demonstrate strict vs lenient behavior - Point to
core/exceptions.pyto explain secure, structured error handling - Export
/openapi.jsonand show TypeScript generation for frontend sync
- React/Next.js playground: Monaco JSON editor + live validation + error highlighting
- WebSocket/SSE endpoint for real-time validation feedback
- GitHub Actions CI:
pytest,ruff,mypy, coverage threshold - OpenAPI TypeScript client generator (
quicktype/openapi-generator) - Rate limiting & caching for
/lab/playground/*endpoints
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open a Pull Request
Code Standards:
- Follow PEP 8 for Python style
- Add docstrings to all public functions/classes
- Include tests for new features
- Keep validation logic isolated in
app/models/
MIT License. See LICENSE for details.
Built with โค๏ธ for developers who believe type safety shouldn't slow them down.
Questions? Open an issue or reach out directly.
