Как работает механизм внедрения зависимостей (Dependency Injection) в FastAPI

Ответ

Механизм внедрения зависимостей (Dependency Injection, DI) в FastAPI — это мощная система, которая позволяет объявлять зависимости (например, сессию БД, аутентификацию пользователя, параметры запроса) и автоматически «внедрять» их в обработчики эндпоинтов.

Это достигается с помощью функции-декоратора Depends.

Основной принцип работы:

  1. Объявление зависимости: Зависимость — это обычная функция (синхронная или асинхронная) или класс, который может принимать параметры и возвращать значение.
  2. Внедрение в эндпоинт: В сигнатуре функции-обработчика маршрута вы указываете параметр, значением по умолчанию для которого является Depends(ваша_зависимость).
  3. Автоматическое выполнение: Перед выполнением кода обработчика FastAPI вызывает функцию-зависимость, дожидается ее результата и передает его в качестве аргумента в ваш обработчик.

Пример:

from typing import Optional
from fastapi import Depends, FastAPI

app = FastAPI()

# 1. Объявляем зависимость - функцию для обработки общих параметров пагинации
def get_pagination_params(skip: int = 0, limit: int = 100):
    """Эта функция будет вызвана для каждого запроса к /items/."""
    return {"skip": skip, "limit": limit}

# 2. Внедряем зависимость в обработчик с помощью Depends
@app.get("/items/")
async def read_items(pagination: dict = Depends(get_pagination_params)):
    # 3. FastAPI автоматически вызовет get_pagination_params
    # и передаст результат в аргумент `pagination`
    return {"message": "Items list", "pagination": pagination}

@app.get("/users/")
async def read_users(pagination: dict = Depends(get_pagination_params)):
    # Зависимость можно переиспользовать в разных эндпоинтах
    return {"message": "Users list", "pagination": pagination}

Ключевые преимущества и особенности:

  • Переиспользование кода: Одна и та же зависимость (например, проверка прав доступа) может использоваться в десятках эндпоинтов.
  • Кеширование: В рамках одного запроса результат выполнения зависимости кешируется. Если Depends(get_pagination_params) используется несколько раз в одном эндпоинте, функция get_pagination_params будет вызвана только один раз.
  • Иерархия зависимостей: Зависимости могут зависеть от других зависимостей, создавая сложные цепочки.
  • Упрощение тестирования: При тестировании можно легко подменить реальную зависимость (например, подключение к БД) на тестовый mock-объект.
  • Интеграция с OpenAPI: FastAPI автоматически анализирует зависимости и добавляет необходимые параметры (как skip и limit в примере) в документацию Swagger/ReDoc.