Почему Depends в FastAPI вызывается один раз: кэш внутри запроса
Маршрут получает пользователя напрямую и через проверку прав. В обеих ветках указана одна функция зависимости. Вы ожидаете два обращения к базе, но видите одно. Это штатное поведение: FastAPI переиспользует результат одинаковой зависимости в пределах одного запроса.
Кэш запроса не становится глобальным
Переиспользование помогает нескольким зависимостям работать с одним пользователем или одной Session. Результат живёт в текущем запросе. Следующий запрос снова вычислит зависимость. Это не кэш между пользователями и не способ хранить данные процесса. Если нужно кеширование каталога на минуту, проектируйте его отдельно с явным ключом и временем жизни.
use_cache=False позволяет потребителю получить новое вычисление вместо чтения уже сохранённого результата. Применяйте его, когда повторное чтение действительно имеет смысл: например, для изменяющегося состояния внутри одной операции. Для текущего пользователя и сессии базы обычное переиспользование чаще является желательным свойством.
Наблюдаем число вызовов на HTTP-запросе
Счётчик ниже делает результат видимым. На /cached две ветки используют один результат. На /fresh вторая ветка просит новый. Между запросами счётчик растёт, и это дополнительно показывает границу кэша. Нужны FastAPI и HTTPX.
Сохраните весь блок в файл и запустите Python 3.11+ в отдельном окружении с пакетами fastapi, httpx. Для моделей используется Pydantic v2; отдельный сервер для TestClient не нужен.
from typing import Annotated
from fastapi import FastAPI, Depends
from fastapi.testclient import TestClient
app = FastAPI()
calls = 0
def value():
global calls
calls += 1
return calls
@app.get("/cached")
def cached(a: Annotated[int, Depends(value)], b: Annotated[int, Depends(value)]):
return [a, b]
@app.get("/fresh")
def fresh(a: Annotated[int, Depends(value)],
b: Annotated[int, Depends(value, use_cache=False)]):
return [a, b]
with TestClient(app) as client:
assert client.get("/cached").json() == [1, 1]
assert client.get("/cached").json() == [2, 2]
assert client.get("/fresh").json() == [3, 4]
assert calls == 4
print("dependency executions:", calls)Какое поведение зафиксировать в рабочем API
Для сессии базы важно, чтобы транзакционная логика не получила случайно две независимые Session. Сохраните get_db одной функцией и переиспользуйте её в зависимостях. Две функции с одинаковым телом остаются разными зависимостями: сходство исходного кода не делает их одним ключом кэша.
Для проверки прав, наоборот, не считайте повторное выполнение доказательством безопасности. Правильность зависит от того, какие данные проверяются и кому разрешён ресурс. Кэшированная загрузка пользователя внутри запроса обычно корректна; устаревание данных между запросами решается на другой границе.
Почему счётчик не должен попасть в production
Глобальное число здесь только наблюдает учебный эксперимент. В нескольких процессах у каждого будет собственное значение, а параллельные запросы изменят порядок. Для рабочего наблюдения используйте журналы с идентификатором запроса или метрики вызовов, не превращая счётчик в источник бизнес-данных.
Если зависимость возвращает изменяемый объект, две ветки видят именно один результат. Изменение объекта в первой ветке может быть видно во второй. Предпочитайте не менять общий результат разбора настроек или параметров, а для ресурсов вроде Session учитывайте совместное использование явно. Это помогает читать граф зависимостей как порядок получения данных, а не как набор независимых вызовов.
Следующая практика
В открытом уроке о зависимостях вы увидите, как FastAPI передаёт результат Depends в маршрут. Продолжите экспериментом со счётчиком из статьи, чтобы отдельно понять переиспользование результата внутри запроса. Начните с бесплатного урока Depends.
Продолжите бесплатную программу FastAPI до базы, авторизации и тестов: граф зависимостей станет частью цельного backend. Сравнивайте время жизни пользователя, Session и настроек, а не применяйте одинаковый кэш ко всем данным. Откройте программу курса.
Продолжить на практике
- FastAPI для начинающих: API с базой данных и тестами ↗
Соберёте свой первый полноценный backend на FastAPI: с базой данных, регистрацией, JWT-авторизацией и автотестами. 34 коротких урока и 140 заданий с проверкой — бесплатно.
