Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Классы в FastAPI
FastAPI активно использует различные классы для построения надёжных и типобезопасных API приложений. Вот основные категории классов, которые я использую в повседневной разработке.
1. Pydantic модели (BaseModel)
Основной способ определения схем данных и валидации:
from pydantic import BaseModel, Field, validator
from typing import Optional, List
class UserCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=100)
email: str = Field(..., regex=r'^[\w\.-]+@[\w\.-]+\.\w+$')
age: Optional[int] = Field(None, ge=0, le=150)
@validator('name')
def name_not_empty(cls, v):
if not v.strip():
raise ValueError('Имя не может быть пустым')
return v.title()
class UserResponse(BaseModel):
id: int
name: str
email: str
age: Optional[int]
class Config:
from_attributes = True # ORM mode для SQLAlchemy
2. APIRouter
Для организации маршрутов в отдельные файлы:
from fastapi import APIRouter, Depends, HTTPException
from typing import List
router = APIRouter(
prefix='/api/v1/users',
tags=['users'],
responses={404: {'description': 'Not found'}}
)
@router.get('', response_model=List[UserResponse])
async def get_users(skip: int = 0, limit: int = 10):
"""Получить список всех пользователей."""
users = db.query(User).offset(skip).limit(limit).all()
return users
@router.post('', response_model=UserResponse, status_code=201)
async def create_user(user: UserCreate):
"""Создать нового пользователя."""
db_user = User(**user.dict())
db.add(db_user)
db.commit()
return db_user
3. Dependency Injection (Depends)
Для внедрения зависимостей:
from fastapi import Depends, HTTPException
from sqlalchemy.orm import Session
def get_db():
"""Зависимость для получения сессии БД."""
db = SessionLocal()
try:
yield db
finally:
db.close()
def get_current_user(
token: str = Depends(oauth2_scheme),
db: Session = Depends(get_db)
) -> User:
"""Получить текущего аутентифицированного пользователя."""
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get('sub')
if username is None:
raise HTTPException(status_code=401, detail='Invalid credentials')
user = db.query(User).filter(User.username == username).first()
if user is None:
raise HTTPException(status_code=404, detail='User not found')
return user
@router.get('/me', response_model=UserResponse)
async def get_profile(current_user: User = Depends(get_current_user)):
"""Получить профиль текущего пользователя."""
return current_user
4. HTTPException
Для возврата HTTP ошибок:
from fastapi import HTTPException
from starlette import status
@router.get('/{user_id}', response_model=UserResponse)
async def get_user(user_id: int, db: Session = Depends(get_db)):
"""Получить пользователя по ID."""
user = db.query(User).filter(User.id == user_id).first()
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail='User not found'
)
return user
5. Request и Response
Для работы с запросами и ответами:
from fastapi import Request, Response
from fastapi.responses import JSONResponse, FileResponse, StreamingResponse
@router.post('/upload')
async def upload_file(request: Request):
"""Обработать загруженный файл."""
body = await request.body()
return {'size': len(body)}
@router.get('/download')
async def download_file():
"""Скачать файл."""
return FileResponse(
path='data.csv',
filename='exported_data.csv',
media_type='text/csv'
)
@router.get('/stream')
async def stream_data():
"""Потоковая передача данных."""
async def generate():
for i in range(10):
yield f'data: {i}\n'
return StreamingResponse(generate(), media_type='text/event-stream')
6. UploadFile
Для загрузки файлов:
from fastapi import UploadFile, File
@router.post('/upload-file')
async def upload_single_file(file: UploadFile = File(...)):
"""Загрузить один файл."""
contents = await file.read()
return {
'filename': file.filename,
'content_type': file.content_type,
'size': len(contents)
}
@router.post('/upload-multiple')
async def upload_multiple_files(files: List[UploadFile] = File(...)):
"""Загрузить несколько файлов."""
results = []
for file in files:
contents = await file.read()
results.append({
'filename': file.filename,
'size': len(contents)
})
return results
7. Query параметры
from fastapi import Query
@router.get('/search')
async def search_users(
q: str = Query(..., min_length=1, max_length=50),
skip: int = Query(0, ge=0),
limit: int = Query(10, ge=1, le=100),
sort: str = Query('name', regex='^(name|email|age)$')
):
"""Поиск пользователей с фильтрацией."""
return {'query': q, 'skip': skip, 'limit': limit, 'sort': sort}
8. OAuth2PasswordBearer
Для аутентификации с токенами:
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from passlib.context import CryptContext
import jwt
from datetime import datetime, timedelta
oauth2_scheme = OAuth2PasswordBearer(tokenUrl='token')
pwd_context = CryptContext(schemes=['bcrypt'])
SECRET_KEY = 'your-secret-key-change-me'
ALGORITHM = 'HS256'
@router.post('/token')
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
"""Получить JWT токен."""
user = authenticate_user(form_data.username, form_data.password)
if not user:
raise HTTPException(status_code=401, detail='Invalid credentials')
access_token_expires = timedelta(hours=24)
expire = datetime.utcnow() + access_token_expires
token_data = {'sub': user.username, 'exp': expire}
encoded_jwt = jwt.encode(token_data, SECRET_KEY, algorithm=ALGORITHM)
return {'access_token': encoded_jwt, 'token_type': 'bearer'}
9. Background Tasks
Для выполнения фоновых задач:
from fastapi import BackgroundTasks
import time
def send_email_async(email: str, message: str):
"""Отправить email в фоне (имитация)."""
time.sleep(2)
print(f'Email sent to {email}: {message}')
@router.post('/send-notification')
async def send_notification(
email: str,
background_tasks: BackgroundTasks
):
"""Отправить уведомление и вернуться немедленно."""
background_tasks.add_task(send_email_async, email, 'Hello!')
return {'message': 'Notification scheduled'}
10. SQLAlchemy модели
Основные классы для работы с БД:
from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
from datetime import datetime
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(100), nullable=False)
email = Column(String(100), unique=True, nullable=False)
password_hash = Column(String(255), nullable=False)
created_at = Column(DateTime, default=datetime.utcnow)
def __repr__(self):
return f'<User(id={self.id}, name={self.name}, email={self.email})>'
11. Класс FastAPI
Главное приложение:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI(
title='My API',
description='API documentation',
version='1.0.0'
)
app.add_middleware(
CORSMiddleware,
allow_origins=['http://localhost:3000'],
allow_credentials=True,
allow_methods=['*'],
allow_headers=['*']
)
app.include_router(router, prefix='/api/v1')
@app.get('/')
async def root():
return {'message': 'Hello World'}
12. Кастомные исключения
from fastapi import HTTPException
from starlette import status
class UserNotFound(HTTPException):
def __init__(self, user_id: int):
super().__init__(
status_code=status.HTTP_404_NOT_FOUND,
detail=f'User with id {user_id} not found'
)
class InsufficientPermissions(HTTPException):
def __init__(self):
super().__init__(
status_code=status.HTTP_403_FORBIDDEN,
detail='Insufficient permissions'
)
@router.delete('/{user_id}')
async def delete_user(
user_id: int,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Удалить пользователя."""
if current_user.id != user_id and not current_user.is_admin:
raise InsufficientPermissions()
user = db.query(User).filter(User.id == user_id).first()
if not user:
raise UserNotFound(user_id)
db.delete(user)
db.commit()
return {'detail': 'User deleted'}
Все эти классы вместе создают мощную и гибкую систему для разработки профессиональных API приложений на Python.