Files
fastapi-conventions/sources/full-stack-fastapi-template.md
2026-06-01 21:42:05 +00:00

4.8 KiB

Full-stack FastAPI Template source notes

Repo: fastapi/full-stack-fastapi-template Local checkout: /home/ubuntu/repos/rodin-sources/full-stack-fastapi-template

Why this repo was chosen

  • This template is a production-oriented FastAPI service skeleton, so it is useful for spotting conventions that survive outside toy examples: central assembly, typed dependency aliases, explicit schema boundaries, and visible test resource lifetimes.
  • It is also valuable because it includes a few pragmatic exceptions that should not be over-generalized.

Repeated patterns

1) Route modules are grouped by feature and assembled centrally

  • backend/app/api/main.py:6-14 creates a single api_router, includes feature routers (login, users, utils, items), and conditionally includes a private router only in local environments.
  • backend/app/main.py:17-33 creates the app, configures OpenAPI identity generation and CORS middleware, then mounts the API router under the versioned prefix.

Why chosen:

  • This is the top-level assembly pattern for the template, not a side example.

Caveat / counterexample:

  • backend/app/api/main.py:13-14 shows an environment-specific router include. Good synthesis should treat this as a deliberate local-only escape hatch, not a reason to scatter router registration across arbitrary modules.

Implication for synthesis:

  • Favor one central API router and one central app assembly module.
  • Mention that environment-specific routes can still be expressed centrally.

2) Dependencies own session/auth wiring, and typed aliases keep route signatures concise

  • backend/app/api/deps.py:21-27 defines get_db() and publishes SessionDep / TokenDep as Annotated[..., Depends(...)] aliases.
  • backend/app/api/deps.py:30-57 decodes the token, validates it with TokenPayload, loads the user, and raises semantic HTTP errors for invalid credentials, missing users, inactive users, and insufficient privileges.
  • backend/app/api/routes/items.py:13-16, 48-49, 61-64, 75-82, and 99-102 repeatedly inject SessionDep and CurrentUser directly in handler signatures.

Why chosen:

  • The dependency alias pattern is repeated across route handlers, not used once.

Implication for synthesis:

  • Strong evidence for typed dependency aliases when the same collaborators appear across many handlers.
  • Shared auth/session logic belongs in dependencies, not repeated inline in each route.

3) Schema transitions stay explicit at route boundaries

  • backend/app/api/routes/items.py:44-45 converts ORM/domain objects to ItemPublic before constructing the collection response.
  • backend/app/api/routes/items.py:61-72 accepts ItemCreate, validates it into an Item with owner_id injected, persists it, and returns the created object.
  • backend/app/api/routes/items.py:91-96 uses item_in.model_dump(exclude_unset=True) before applying a partial update.

Why chosen:

  • The route code repeatedly marks transitions between input schema, persistence model, and output schema.

Caveat / counterexample:

  • backend/app/api/routes/items.py:48-58, 75-96, and 99-113 still return ORM objects directly in some single-item handlers while relying on response_model to shape output. So the template mixes explicit conversion with response-model-driven shaping; future synthesis should describe that nuance instead of claiming one exclusive pattern.

Implication for synthesis:

  • Prefer explicit schema boundaries, especially for collections and patch-style updates.
  • When handlers return domain objects directly, note that response_model is still doing boundary work.

4) Tests keep DB lifetime and cleanup visible

  • backend/tests/conftest.py:15-24 creates a session fixture, initializes the DB once, yields the session, then deletes Item and User rows and commits cleanup.
  • backend/tests/conftest.py:27-30 keeps the test client lifecycle explicit with a context-managed TestClient fixture.

Why chosen:

  • This is the template's default testing setup, so it is strong evidence for visible resource lifetime management.

Strong citation candidates

  • Central API router assembly with local-only conditional include: backend/app/api/main.py:6-14
  • Typed dependency aliases: backend/app/api/deps.py:21-27
  • Auth dependency handles token decode + user lookup + semantic errors: backend/app/api/deps.py:30-57
  • Explicit patch update boundary via model_dump(exclude_unset=True): backend/app/api/routes/items.py:91-96
  • Test DB lifetime and cleanup: backend/tests/conftest.py:15-24

Pattern candidates supported by this repo

  • centralize app and API router assembly
  • use typed dependency aliases for repeated collaborators
  • keep auth/session logic in dependencies
  • keep request/update/response schema transitions explicit
  • keep test resource lifetime and cleanup visible