Знакомство с зависимостями (Depends) в FastAPI
FastAPI предоставляет мощный инструмент для работы с зависимостями — функцию Depends, которая позволяет организовать повторно используемую логику, обрабатывать параметры, управлять состоянием и легко интегрировать внешние сервисы. Зависимости облегчают разработку сложных приложений, помогая структурировать код и избегать дублирования.
В этой статье мы рассмотрим основные возможности Depends
, примеры использования и способы их настройки.
Что такое зависимости в FastAPI?
Зависимости (Dependencies) в FastAPI — это способ определить общий функционал, который можно подключить к маршрутам (endpoints). Зависимости позволяют:
- Валидировать параметры запросов,
- Обеспечивать авторизацию и аутентификацию,
- Подключать базы данных или другие сервисы,
- Выполнять любую повторно используемую логику.
FastAPI автоматически вызывает зависимости, разрешает их и передаёт результаты в функции обработчиков.
Представь, что ты — кот, и тебе нужен человек, чтобы открыть банку корма. Ты не открываешь каждую банку сам (да у тебя и лапки!). Вместо этого ты зовёшь человека: "Мяу!" — и он делает это за тебя.
Depends в FastAPI работает так же! Ты просто говоришь: "Мне нужен кто-то, чтобы сделать это за меня", а FastAPI зовёт "человека" (функцию) и передаёт тебе готовый результат.
Простой пример зависимости
Начнём с простого примера: мы создадим зависимость, которая возвращает значение, и подключим её к маршруту.
from fastapi import Depends, FastAPI app = FastAPI() def common_dependency(): return {"message": "Hello from dependency!"} @app.get("/") def read_root(dep=Depends(common_dependency)): return dep
Что здесь происходит:
- Функция
common_dependency
возвращает объект. Depends(common_dependency)
подключает эту зависимость к маршруту.- Возвращённое значение из зависимости (
{"message": "Hello from dependency!"}
) передаётся в обработчик.
{"message": "Hello from dependency!"}
Зависимости с параметрами
Вы можете передавать параметры в зависимости. Например, создадим зависимость для проверки доступа, используя параметр token
из заголовков.
from fastapi import Depends, FastAPI, Header, HTTPException app = FastAPI() def get_token_header(token: str = Header(...)): if token != "secret-token": raise HTTPException(status_code=403, detail="Invalid token") return token @app.get("/protected/") def protected_route(token=Depends(get_token_header)): return {"message": "Access granted"}
Объяснение:
- Зависимость
get_token_header
получает заголовокtoken
. - Если токен неправильный, вызывается ошибка
HTTPException
. - Если токен корректен, маршрут возвращает
{"message": "Access granted"}
.
Зависимости с состоянием (stateful dependencies)
Для работы с объектами, которые нужно сохранять между запросами (например, подключение к базе данных), можно использовать зависимости с состоянием. Обычно это делается с помощью контекстных менеджеров или специальных классов.
Пример: подключение к базе данных
from fastapi import Depends, FastAPI from sqlalchemy.orm import Session app = FastAPI() # Фейковая функция для создания сессии базы данных def get_db(): db = Session() # Подключение к базе данных try: yield db # Возвращаем сессию finally: db.close() # Закрываем сессию после завершения работы @app.get("/items/") def read_items(db: Session = Depends(get_db)): return {"db_status": "Connected"}
Объяснение:
get_db
создаёт и возвращает сессию базы данных с помощьюyield
.- После завершения запроса выполняется блок
finally
, который закрывает сессию. Depends(get_db)
передаёт объектdb
в обработчик.
Использование классов как зависимостей
Зависимости можно организовать в виде классов, что удобно для работы с конфигурациями или общими данными.
Пример: зависимости через класс
from fastapi import Depends, FastAPI app = FastAPI() class Config: def __init__(self, env: str): self.env = env def get_config(env: str = "production"): return Config(env) @app.get("/config/") def get_config_route(config: Config = Depends(get_config)): return {"environment": config.env}
Объяснение:
- Класс
Config
описывает конфигурацию. - Функция
get_config
возвращает экземпляр класса, и его можно настроить через параметры (например,env
).
{"environment": "production"}
Зависимости для повторного использования
FastAPI позволяет повторно использовать зависимости между разными маршрутами или группами маршрутов с помощью APIRouter.
from fastapi import APIRouter, Depends, FastAPI app = FastAPI() router = APIRouter() def common_dependency(): return {"message": "Shared dependency"} @router.get("/route1/") def route1(dep=Depends(common_dependency)): return dep @router.get("/route2/") def route2(dep=Depends(common_dependency)): return dep app.include_router(router)
Объяснение:
- Зависимость
common_dependency
используется в обоих маршрутах. - APIRouter помогает группировать маршруты и подключать зависимости для всей группы.
Сложные зависимости: вложенность
Зависимости могут быть вложенными. Например, одна зависимость может использовать другую.
Пример вложенной зависимости
def verify_token(token: str = Header(...)): if token != "secret-token": raise HTTPException(status_code=403, detail="Invalid token") return token def get_current_user(token: str = Depends(verify_token)): return {"username": "test_user"} @app.get("/users/me") def read_current_user(user=Depends(get_current_user)): return user
Объяснение:
verify_token
проверяет токен.get_current_user
использует токен для получения текущего пользователя.- Обработчик
read_current_user
получает данные пользователя из зависимостиget_current_user
.
Зависимости с асинхронными функциями
FastAPI полностью поддерживает асинхронные зависимости. Это полезно для операций, таких как асинхронное подключение к базе данных или вызовы внешних API.
import asyncio async def async_dependency(): await asyncio.sleep(1) # Имитация длительной операции return {"status": "Success"} @app.get("/async/") async def async_route(dep=Depends(async_dependency)): return dep
Заключение
FastAPI делает работу с зависимостями гибкой и удобной. Depends
позволяет организовывать повторно используемую логику, проверять параметры, подключать внешние сервисы и управлять состоянием приложения. Вот ключевые моменты:
- Простые зависимости облегчают проверку данных и выполнение общей логики.
- Контекстные зависимости подходят для управления подключениями, например, к базе данных.
- Классы-зависимости делают код более структурированным и масштабируемым.
- Асинхронные зависимости полезны для высоконагруженных приложений.
Использование зависимостей помогает сделать ваш код чище, API — надёжнее, а разработку — проще. FastAPI снова показывает, почему он такой удобный инструмент для построения сложных веб-приложений! 🚀