Dependency Injection

FastAPI использует DI почти везде: для подключения к БД, авторизации, конфига, reusable-логики. Идея — функция объявляет, что ей нужно, фреймворк это предоставляет.

Базовая форма

from fastapi import Depends

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.get("/items")
async def list_items(db: Session = Depends(get_db)):
    return db.query(Item).all()

yield делает из зависимости контекстный менеджер — finally сработает гарантированно.

Цепочки и кэширование

Зависимости могут зависеть друг от друга, и в рамках одного запроса результат кэшируется на одном yield-уровне:

flowchart TD
    A[Request /items] --> B[get_current_user]
    B --> C[get_db]
    B --> D[get_settings]
    A --> C

get_db будет вызван один раз, даже если две зависимости его запросили.

Классы как зависимости

Любой callable работает. Класс с __init__ тоже:

class Paginator:
    def __init__(self, page: int = 1, size: int = 20):
        self.page = page
        self.size = size

@app.get("/things")
async def list_things(p: Paginator = Depends()):
    ...

page и size автоматически станут query-параметрами.

Когда НЕ использовать DI

  • Простая трансформация данных — обычная функция проще
  • Зависимость нужна только в одном эндпоинте и больше нигде
  • Побочный эффект, не относящийся к запросу (используй lifespan)

Связанные заметки