7.7 KiB
7.7 KiB
name, description
| name | description |
|---|---|
| fastapi-style | This skill should be used when writing Python and FastAPI code following opinionated best practices. It applies when building APIs, creating Pydantic models, working with SQLAlchemy, or any FastAPI application. Triggers on FastAPI code generation, API design, refactoring requests, code review, or when discussing async Python patterns. Embodies thin routers, rich Pydantic models, dependency injection, async-first design, and the "explicit is better than implicit" philosophy. |
<essential_principles>
Core Philosophy
"Explicit is better than implicit. Simple is better than complex."
The FastAPI Way:
- Thin routers, rich Pydantic models with validation
- Dependency injection for everything
- Async-first with SQLAlchemy 2.0
- Type hints everywhere - let the tools help you
- Settings via pydantic-settings, not raw env vars
- Database-backed solutions where possible
What to deliberately avoid:
- Flask patterns (global request context)
- Django ORM in FastAPI (use SQLAlchemy 2.0)
- Synchronous database calls (use async)
- Manual JSON serialization (Pydantic handles it)
- Global state (use dependency injection)
*imports (explicit imports only)- Circular imports (proper module structure)
Development Philosophy:
- Type everything - mypy should pass
- Fail fast with descriptive errors
- Write-time validation over read-time checks
- Database constraints complement Pydantic validation
- Tests are documentation </essential_principles>
- Routers - Route organization, dependency injection, response models
- Models - Pydantic schemas, SQLAlchemy models, validation patterns
- Database - SQLAlchemy 2.0 async, Alembic migrations, transactions
- Testing - pytest, httpx TestClient, fixtures, async testing
- Security - OAuth2, JWT, permissions, CORS, rate limiting
- Background Tasks - Celery, ARQ, or FastAPI BackgroundTasks
- Code Review - Review code against FastAPI best practices
- General Guidance - Philosophy and conventions
Specify a number or describe your task.
| Response | Reference to Read |
|---|---|
| 1, router, route, endpoint | routers.md |
| 2, model, pydantic, schema, sqlalchemy | models.md |
| 3, database, db, alembic, migration, transaction | database.md |
| 4, test, testing, pytest, fixture | testing.md |
| 5, security, auth, oauth, jwt, permission | security.md |
| 6, background, task, celery, arq, queue | background_tasks.md |
| 7, review | Read all references, then review code |
| 8, general task | Read relevant references based on context |
After reading relevant references, apply patterns to the user's code.
<quick_reference>
Project Structure
app/
├── main.py # FastAPI app creation, middleware
├── config.py # Settings via pydantic-settings
├── dependencies.py # Shared dependencies
├── database.py # Database session, engine
├── models/ # SQLAlchemy models
│ ├── __init__.py
│ ├── base.py # Base model class
│ └── user.py
├── schemas/ # Pydantic models
│ ├── __init__.py
│ └── user.py
├── routers/ # API routers
│ ├── __init__.py
│ └── users.py
├── services/ # Business logic (if needed)
├── utils/ # Shared utilities
└── tests/
├── conftest.py # Fixtures
└── test_users.py
Naming Conventions
Pydantic Schemas:
UserCreate- input for creationUserUpdate- input for updates (all fields Optional)UserRead- output representationUserInDB- internal with hashed password
SQLAlchemy Models: Singular nouns (User, Item, Order)
Routers: Plural resource names (users.py, items.py)
Dependencies: Verb phrases (get_current_user, get_db_session)
Type Hints
# Always type function signatures
async def get_user(
user_id: int,
db: AsyncSession = Depends(get_db),
) -> User:
...
# Use Annotated for dependency injection
from typing import Annotated
CurrentUser = Annotated[User, Depends(get_current_user)]
DBSession = Annotated[AsyncSession, Depends(get_db)]
Response Patterns
# Explicit response_model
@router.get("/users/{user_id}", response_model=UserRead)
async def get_user(user_id: int, db: DBSession) -> User:
...
# Status codes
@router.post("/users", status_code=status.HTTP_201_CREATED)
async def create_user(...) -> UserRead:
...
# Multiple response types
@router.get("/users/{user_id}", responses={404: {"model": ErrorResponse}})
Error Handling
from fastapi import HTTPException, status
# Specific exceptions
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found",
)
# Custom exception handlers
@app.exception_handler(ValidationError)
async def validation_exception_handler(request, exc):
return JSONResponse(status_code=422, content={"detail": exc.errors()})
Dependency Injection
# Simple dependency
async def get_db() -> AsyncGenerator[AsyncSession, None]:
async with async_session() as session:
yield session
# Parameterized dependency
def get_pagination(
skip: int = Query(0, ge=0),
limit: int = Query(100, ge=1, le=1000),
) -> dict:
return {"skip": skip, "limit": limit}
# Class-based dependency
class CommonQueryParams:
def __init__(self, q: str | None = None, skip: int = 0, limit: int = 100):
self.q = q
self.skip = skip
self.limit = limit
</quick_reference>
<reference_index>
Domain Knowledge
All detailed patterns in references/:
| File | Topics |
|---|---|
| routers.md | Route organization, dependency injection, response models, middleware, versioning |
| models.md | Pydantic schemas, SQLAlchemy models, validation, serialization, mixins |
| database.md | SQLAlchemy 2.0 async, Alembic migrations, transactions, connection pooling |
| testing.md | pytest, httpx TestClient, fixtures, async testing, mocking patterns |
| security.md | OAuth2, JWT, permissions, CORS, rate limiting, secrets management |
| background_tasks.md | FastAPI BackgroundTasks, Celery, ARQ, task patterns |
| </reference_index> |
<success_criteria> Code follows FastAPI best practices when:
- Routers are thin, focused on HTTP concerns only
- Pydantic models handle all validation and serialization
- SQLAlchemy 2.0 async patterns used correctly
- Dependencies injected, not imported as globals
- Type hints on all function signatures
- Settings via pydantic-settings
- Tests use pytest with async support
- Error handling is explicit and informative
- Security follows OAuth2/JWT standards
- Background tasks use appropriate tool for the job </success_criteria>
Key Resources: