Как устроено внедрение зависимостей в FastAPI и какую роль играет Pydantic?
Короткий ответ
- Depends объявляет зависимость параметром эндпоинта
- FastAPI сам строит и кэширует граф зависимостей на запрос
- Зависимость-генератор с yield освобождает ресурсы (сессия БД)
- Pydantic валидирует вход по аннотациям и сериализует ответ
- Из типов автоматически строится OpenAPI-документация
- В тестах зависимости подменяются через dependency_overrides
FastAPI через Depends собирает зависимости по аннотациям и кэширует их в рамках запроса, а Pydantic превращает типы в валидацию, сериализацию и OpenAPI-схему.
Как сказать вслух
пример ответаВ FastAPI зависимости объявляются прямо в сигнатуре эндпоинта через Depends: нужна сессия базы или текущий пользователь — просто указываю параметр, и фреймворк сам его создаст и передаст. Зависимости могут зависеть друг от друга, в рамках одного запроса результат кэшируется, а вариант с yield работает как контекстный менеджер — удобно закрывать сессию. Pydantic при этом валидирует входные данные по аннотациям и генерирует документацию. В тестах всё это легко подменяется.
Подробный ответ
Основной ответ
FastAPI читает сигнатуру эндпоинта: path- и query-параметры берёт из простых типов, тело — из моделей Pydantic, а параметры с Depends(func) разрешает, вызывая функцию-зависимость. Зависимости образуют граф (могут иметь свои Depends), результат по умолчанию кэшируется в рамках запроса. Зависимость-генератор с yield выполняет код после yield по завершении запроса — стандартный способ выдать и закрыть сессию БД. Pydantic v2 валидирует и приводит типы входных данных, возвращая 422 с понятными ошибками, сериализует ответ по response_model и поставляет JSON Schema для автодокументации /docs. Для тестов app.dependency_overrides позволяет подменить любую зависимость заглушкой без патчинга.
Ключевые моменты
- Граф зависимостей. Зависимости вкладываются друг в друга: get_current_user зависит от get_db и токена; FastAPI разрешает цепочку сам.
- yield-зависимости. Код до yield — на входе, после — на выходе; так управляют сессиями, транзакциями и внешними клиентами.
- Pydantic v2. Валидация на ядре на Rust, строгие и гибкие режимы, model_validate/model_dump; ошибки клиенту — структурированный 422.
- Тестируемость. dependency_overrides подменяет БД или авторизацию в TestClient — юнит-тесты без реальной инфраструктуры.
Практический контекст
На собеседовании по FastAPI это центральная тема: просят объяснить, как отдать сессию БД в эндпоинт, как сделать проверку прав или как подменить зависимость в тесте. Интервьюер смотрит, понимает ли кандидат, что DI здесь декларативный и завязан на аннотации, и отличает ли async- и sync-зависимости (sync уходят в пул потоков).
Пример кода
from fastapi import FastAPI, Depends
from pydantic import BaseModel
app = FastAPI()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
class UserIn(BaseModel):
email: str
age: int
@app.post("/users")
def create_user(user: UserIn, db=Depends(get_db)):
return {"email": user.email}Частые ошибки
- Создают сессию БД глобально вместо yield-зависимости и ловят утечки соединений
- Пишут def-эндпоинты с блокирующим кодом внутри async def, блокируя событийный цикл
- Патчат модули в тестах вместо штатного dependency_overrides