Знакомство с зависимостями (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 снова показывает, почему он такой удобный инструмент для построения сложных веб-приложений! 🚀