mcpbeat

Python Fastapi Patterns

aiskillstore/python-fastapi-patterns

FastAPI web framework patterns. Triggers on: fastapi, api endpoint, dependency injection, pydantic model, openapi, swagger, starlette, async api, rest api, uvicorn.

This is a copy. The original lives at comeonoliver/python-fastapi-patterns.

30k tokens
context cost
the whole folder, loaded on every use
8
files
ships runnable scripts
0
copies elsewhere
how many repositories repackaged it
404
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/aiskillstore/marketplace --skill python-fastapi-patterns

What comes with it

116 227 bytes besides the instruction
assets/fastapi-template.py
references/background-tasks.md
references/dependency-injection.md
references/middleware-patterns.md
references/validation-serialization.md
scripts/scaffold-api.sh
skill-report.json

The instruction itself

12 sections, as written by the author

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 hints
  • python-async-patterns - Async endpoint patterns

Related Skills:

  • python-database-patterns - SQLAlchemy integration
  • python-observability-patterns - Logging, metrics, tracing middleware
  • python-pytest-patterns - API testing with TestClient

How to use it

Copy the folder

Take aiskillstore/python-fastapi-patterns from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.