FastAPI

Lesson 04

Dependencies as boundaries

Use `Depends` to share request parsing, context, and collaborators without hiding setup inside handlers.

Good Code

api/reviews.py
from typing import Annotated

from fastapi import APIRouter, Depends, Query

router = APIRouter()


async def pagination(
    limit: Annotated[int, Query(le=100)] = 20,
    offset: int = 0,
):
    return {"limit": limit, "offset": offset}


@router.get("/reviews")
async def list_reviews(page: Annotated[dict, Depends(pagination)]):
    return await reviews.list(**page)

Bad Code

api/reviews.py
from fastapi import APIRouter, Request

router = APIRouter()


@router.get("/reviews")
async def list_reviews(request: Request):
    limit = int(request.query_params.get("limit", 20))
    offset = int(request.query_params.get("offset", 0))
    return await reviews.list(limit=limit, offset=offset)

Review Notes

What to review

Good Code

The good version makes pagination a reusable dependency with validation and documentation.

Bad Code

The bad version manually parses query parameters inside the route. Validation, defaults, and reuse are scattered across handlers.

Takeaways

  • FastAPI dependencies make repeated request setup explicit, reusable, and visible in OpenAPI.