Какой паттерн есть в FastAPI, который отличиает его от других фреймворков?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Dependency Injection в FastAPI
Одной из самых отличительных и мощных особенностей FastAPI является встроенная система Dependency Injection (DI). Это паттерн, который выделяет FastAPI среди других Python веб-фреймворков (Flask, Django) своей элегантностью и интеграцией.
Суть паттерна
Dependency Injection позволяет описывать зависимости в функциях-обработчиках, и FastAPI автоматически:
- Разрешает эти зависимости
- Кэширует их в рамках одного запроса
- Внедряет в функцию
- Валидирует и сериализует данные
Базовый пример
from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
app = FastAPI()
def get_db():
# Получаем сессию БД
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/users/{user_id}")
def get_user(user_id: int, db: Session = Depends(get_db)):
# FastAPI автоматически вызовет get_db() и подставит результат
user = db.query(User).filter(User.id == user_id).first()
return user
Преимущества перед другими фреймворками
1. Встроенная поддержка — не нужны сторонние библиотеки вроде dependency-injector или inject.
2. Интеграция с типизацией — FastAPI использует type hints для автоматической валидации:
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
def validate_user(user: User = Depends()):
# FastAPI автоматически валидирует данные из JSON body
return user
@app.post("/users")
def create_user(user: User = Depends(validate_user)):
return user
3. Кэширование на уровне запроса:
def get_current_user(token: str = Header()):
user = parse_token(token) # Вычисляется один раз
return user
@app.get("/profile")
def get_profile(user = Depends(get_current_user)):
return {"profile": user}
@app.get("/posts")
def get_user_posts(user = Depends(get_current_user)):
# user получит ТОТ ЖЕ объект из кэша, не перевычисляется
return [p for p in posts if p.user_id == user.id]
4. Композиция зависимостей — вложенные зависимости работают интуитивно:
def get_current_user(token: str = Header()) -> User:
return parse_token(token)
def get_admin_user(user: User = Depends(get_current_user)) -> User:
if user.role != "admin":
raise HTTPException(status_code=403)
return user
@app.delete("/users/{user_id}")
def delete_user(user_id: int, admin = Depends(get_admin_user)):
# Гарантированно передается только администратор
db.delete_user(user_id)
Отличие от Flask/Django
Flask требует использовать декораторы и контекстные менеджеры для зависимостей:
# Flask - нужны сторонние библиотеки
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
Django имеет встроенные зависимости через settings и middleware, но это менее гибко:
# Django - жестко привязано к settings и ORM
from django.db import connection
FastAPI - всё в одном месте и типизировано:
# FastAPI - явно, типизировано, переиспользуемо
def get_db() -> Generator[Session, None, None]:
db = SessionLocal()
try:
yield db
finally:
db.close()
Сложные сценарии
Условные зависимости:
async def verify_token(request: Request):
token = request.headers.get("Authorization")
if not token:
return None
return parse_token(token)
@app.get("/data")
async def get_data(user = Depends(verify_token)):
if user is None:
return {"public": "data"}
return {"private": "data", "user": user.name}
Итог
Dependency Injection в FastAPI - это не просто удобство, это фундамент архитектуры. Он делает код более тестируемым, модульным и безопасным. Это главное отличие FastAPI от конкурентов на Python.