Что такое Depends в FastAPI и для чего он нужен
Что проверяют
Понимаете ли вы, как FastAPI строит граф зависимостей и что делает с ним на каждом запросе, или просто копировали Depends(get_db) из документации. Следом почти всегда спрашивают, как подменить зависимость в тестах и как работает зависимость с yield.
Как отвечать
Depends объявляет, что параметр обработчика нужно получить вызовом другой функции или класса. На каждом запросе FastAPI обходит граф: у зависимости могут быть свои параметры из query, заголовков, тела и свои Depends, и всё это попадает в валидацию и в OpenAPI-схему.
- современная запись:
db: Annotated[Session, Depends(get_db)]. Тип выносится в алиас вродеSessionDep, документация рекомендует этот стиль с версии 0.95; - зависимости с
yield: код доyieldготовит ресурс, после него освобождает. Классика это сессия базы, которую закрывают вfinally; - кеш в пределах запроса: если зависимость встречается в графе несколько раз, она вызывается один раз. Отключается через
Depends(dep, use_cache=False); - зависимости без результата:
dependencies=[Depends(verify_token)]на роуте, наAPIRouterили на всём приложении, удобно для авторизации; - классы:
Depends()без аргумента берёт класс из аннотации и создаёт экземпляр из параметров запроса; - тесты:
app.dependency_overrides[get_db] = fake_dbподменяет зависимость во всём графе без патчей.
Синхронные def-зависимости FastAPI запускает в пуле потоков, асинхронные выполняются прямо в event loop.
Где спотыкаются
Вызывают зависимость руками: get_db() в сервисе возвращает генератор, а не сессию. Depends работает только в обработчиках и других зависимостях, в Celery-задаче он ничего не внедряет.
Ждут от Depends синглтона. Без дополнительных мер зависимость вызывается на каждом запросе, поэтому настройки оборачивают в @lru_cache, а тяжёлые клиенты создают в lifespan и кладут в app.state.
Забывают очистить dependency_overrides после теста, и подмена протекает в соседние тесты, которые падают в зависимости от порядка запуска.