python-fastapi-patterns
npx machina-cli add skill aiskillstore/marketplace/python-fastapi-patterns --openclawFiles (1)
SKILL.md
5.2 KB
FastAPI Patterns
Modern async API development with FastAPI.
Basic Application
from fastapi import FastAPI
from contextlib import asynccontextmanager
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Application lifespan - startup and shutdown."""
# Startup
app.state.db = await create_db_pool()
yield
# Shutdown
await app.state.db.close()
app = FastAPI(
title="My API",
version="1.0.0",
lifespan=lifespan,
)
@app.get("/")
async def root():
return {"message": "Hello World"}
Request/Response Models
from pydantic import BaseModel, Field, EmailStr
from datetime import datetime
class UserCreate(BaseModel):
"""Request model with validation."""
name: str = Field(..., min_length=1, max_length=100)
email: EmailStr
age: int = Field(..., ge=0, le=150)
class UserResponse(BaseModel):
"""Response model."""
id: int
name: str
email: EmailStr
created_at: datetime
model_config = {"from_attributes": True} # Enable ORM mode
@app.post("/users", response_model=UserResponse, status_code=201)
async def create_user(user: UserCreate):
db_user = await create_user_in_db(user)
return db_user
Path and Query Parameters
from fastapi import Query, Path
from typing import Annotated
@app.get("/users/{user_id}")
async def get_user(
user_id: Annotated[int, Path(..., ge=1, description="User ID")],
):
return await fetch_user(user_id)
@app.get("/users")
async def list_users(
skip: Annotated[int, Query(ge=0)] = 0,
limit: Annotated[int, Query(ge=1, le=100)] = 10,
search: str | None = None,
):
return await fetch_users(skip=skip, limit=limit, search=search)
Dependency Injection
from fastapi import Depends
from typing import Annotated
async def get_db():
"""Database session dependency."""
async with async_session() as session:
yield session
async def get_current_user(
token: Annotated[str, Depends(oauth2_scheme)],
db: Annotated[AsyncSession, Depends(get_db)],
) -> User:
"""Authenticate and return current user."""
user = await authenticate_token(db, token)
if not user:
raise HTTPException(status_code=401, detail="Invalid token")
return user
# Annotated types for reuse
DB = Annotated[AsyncSession, Depends(get_db)]
CurrentUser = Annotated[User, Depends(get_current_user)]
@app.get("/me")
async def get_me(user: CurrentUser):
return user
Exception Handling
from fastapi import HTTPException
from fastapi.responses import JSONResponse
# Built-in HTTP exceptions
@app.get("/items/{item_id}")
async def get_item(item_id: int):
item = await fetch_item(item_id)
if not item:
raise HTTPException(status_code=404, detail="Item not found")
return item
# Custom exception handler
class ItemNotFoundError(Exception):
def __init__(self, item_id: int):
self.item_id = item_id
@app.exception_handler(ItemNotFoundError)
async def item_not_found_handler(request, exc: ItemNotFoundError):
return JSONResponse(
status_code=404,
content={"detail": f"Item {exc.item_id} not found"},
)
Router Organization
from fastapi import APIRouter
# users.py
router = APIRouter(prefix="/users", tags=["users"])
@router.get("/")
async def list_users():
return []
@router.get("/{user_id}")
async def get_user(user_id: int):
return {"id": user_id}
# main.py
from app.routers import users, items
app.include_router(users.router)
app.include_router(items.router, prefix="/api/v1")
Quick Reference
| Feature | Usage |
|---|---|
| Path param | @app.get("/items/{id}") |
| Query param | def f(q: str = None) |
| Body | def f(item: ItemCreate) |
| Dependency | Depends(get_db) |
| Auth | Depends(get_current_user) |
| Response model | response_model=ItemResponse |
| Status code | status_code=201 |
Additional Resources
./references/dependency-injection.md- Advanced DI patterns, scopes, caching./references/middleware-patterns.md- Middleware chains, CORS, error handling./references/validation-serialization.md- Pydantic v2 patterns, custom validators./references/background-tasks.md- Background tasks, async workers, scheduling
Scripts
./scripts/scaffold-api.sh- Generate API endpoint boilerplate
Assets
./assets/fastapi-template.py- Production-ready FastAPI app skeleton
See Also
Prerequisites:
python-typing-patterns- Pydantic models and type hintspython-async-patterns- Async endpoint patterns
Related Skills:
python-database-patterns- SQLAlchemy integrationpython-observability-patterns- Logging, metrics, tracing middlewarepython-pytest-patterns- API testing with TestClient
Source
git clone https://github.com/aiskillstore/marketplace/blob/main/skills/0xdarkmatter/python-fastapi-patterns/SKILL.mdView on GitHub Overview
This skill teaches practical FastAPI patterns for building robust web APIs. It covers startup/shutdown management, request/response validation with Pydantic, dependency injection, exception handling, and router organization to keep code modular and scalable.
How This Skill Works
Leverage FastAPI core features: manage lifecycle with an async lifespan, validate data with Pydantic models, compose dependencies with Depends for clean DI, and structure routes with APIRouter. These patterns enable clean separation of concerns and automatic OpenAPI documentation.
When to Use It
- Starting a new FastAPI project and aiming for maintainable structure
- Needing startup/shutdown tasks like DB pool initialization and cleanup
- Implementing strict input/output validation with Pydantic models
- Building authentication/authorization flows with dependency injection
- Organizing large apps into modular routers while preserving clarity
Quick Start
- Step 1: Create a FastAPI app with a lifespan function and pass it to FastAPI
- Step 2: Define Pydantic models for requests and responses
- Step 3: Add endpoints using decorators, specify response_model, and wire DI with Depends
Best Practices
- Use the lifespan pattern to encapsulate startup/shutdown logic (e.g., DB connections)
- Prefer Pydantic v2 models for request/response validation and use model_config when needed
- Centralize dependencies with Depends and Annotated types for reuse
- Annotate responses with response_model and set appropriate status codes
- Organize routes with APIRouter per module to keep main.py lean
Example Use Cases
- Startup and shutdown of resources via asynccontextmanager lifespan
- Request/response models with UserCreate and UserResponse using Pydantic
- Path and query parameter validation using Path and Query
- Dependency injection for DB sessions and current user via Depends
- Router organization with APIRouter and modular route files
Frequently Asked Questions
Add this skill to your agents