Гайды
Маршрутизация и Dependency Injection в FastAPI
APIRouter и префиксы, Depends и кэш, yield-сессии БД, dependencies на роутере, BackgroundTasks и чек-лист.
~10 мин чтения
Маршрутизация и Dependency Injection в FastAPI
APIRouter дробит приложение на модули; Depends даёт внедрение зависимостей (БД, пользователь, настройки) с кэшированием в рамках запроса. Базовый каркас — Быстрый старт с FastAPI; валидация тел — Pydantic: валидация и сериализация.
1. APIRouter и префиксы
# app/api/routes/users.py
from fastapi import APIRouter
router = APIRouter(prefix="/users", tags=["users"])
@router.get("/")
def list_users():
return []
@router.get("/{user_id}")
def get_user(user_id: int):
return {"id": user_id}
Подключение:
from fastapi import FastAPI
from app.api.routes import users
app = FastAPI()
app.include_router(users.router, prefix="/api/v1")
Итоговый путь: /api/v1/users/, /api/v1/users/{user_id}.
2. Зависимости: функции
from typing import Annotated
from fastapi import Depends, Header
def pagination(skip: int = 0, limit: int = 20):
return {"skip": skip, "limit": min(limit, 100)}
@app.get("/items")
def list_items(page: Annotated[dict, Depends(pagination)]):
return page
Depends(pagination) вызывается при каждом запросе; результат кэшируется для одного и того же набора параметров внутри одного запроса (если зависимость повторно запрошена).
3. Зависимости: классы
class CommonQuery:
def __init__(self, q: str | None = None, debug: bool = False):
self.q = q
self.debug = debug
@app.get("/search")
def search(cq: Annotated[CommonQuery, Depends()]):
return {"q": cq.q, "debug": cq.debug}
Удобно группировать параметры и тестировать изолированно.
4. Вложенные Depends
from fastapi import Depends, Header, HTTPException
def get_token(authorization: str | None = Header(None)) -> str:
if not authorization or not authorization.startswith("Bearer "):
raise HTTPException(401, "Missing token")
return authorization.removeprefix("Bearer ").strip()
def get_current_user(token: Annotated[str, Depends(get_token)]):
return {"sub": "user-1"} # здесь — разбор JWT
@app.get("/me")
def me(user: Annotated[dict, Depends(get_current_user)]):
return user
Полноценный JWT и OAuth2 — в гайде JWT/OAuth2 и в официальном разделе Security.
5. yield в зависимостях (сессия БД)
from collections.abc import AsyncGenerator
from fastapi import Depends
async def get_db() -> AsyncGenerator:
conn = await pool.acquire()
try:
yield conn
finally:
await pool.release(conn)
@app.get("/row")
async def one_row(db = Depends(get_db)):
return await db.fetchrow("SELECT 1 AS n")
Код после yield выполняется при завершении запроса (в т.ч. после ошибки).
6. dependencies на роутере
router = APIRouter(dependencies=[Depends(require_api_key)])
Общие проверки для всех эндпоинтов модуля без дублирования.
7. BackgroundTasks
from fastapi import BackgroundTasks
def write_log(msg: str):
...
@app.post("/notify")
def notify(bg: BackgroundTasks, msg: str):
bg.add_task(write_log, msg)
return {"queued": True}
Не для тяжёлой фоновой работы — для неё отдельный воркер (Celery, RQ) и брокер задач.
8. Порядок маршрутов и mount
FastAPI сопоставляет маршруты в порядке регистрации; более специфичные пути (/items/me) объявляйте выше параметрических (/items/{item_id}), иначе me попадёт в item_id.
app.mount("/static", StaticFiles(...)) для отдачи сборки фронта; mount обычно подключают после API-роутов или на отдельном префиксе, чтобы не перехватывать JSON-эндпоинты.
9. Чек-лист
- Роутеры по домену, единый
prefixверсии API. - Зависимости не тянут тяжёлую работу в импорт-модулей.
-
yield-ресурсы всегда освобождаются вfinally. - Для глобального состояния приложения —
app.state+ lifespan.
Дальше: Быстрый старт · asyncpg · Pydantic · OpenAPI/Swagger · тег FastAPI