Pydantic Schema — валидация и сериализация данных

В этой главе вы узнаете о Pydantic Schema и поймёте его разделение обязанностей с ORM-моделями — это самая основная особенность FastAPI.


Зачем нужна схема?

ORM-модели (models.py) определяют структуру базы данных, но не могут напрямую использоваться для валидации запросов/ответов API.

Причина: ORM-модели содержат логику, специфичную для базы данных (например, связи), и вы не хотите раскрывать все поля в API.

Pydantic-схемаЭто чистый класс данных, специально отвечающий за валидацию и сериализацию ввода/вывода API.

Связь между этими тремя:

客户端 → [Pydantic Schema 校验] → 路由函数 → [ORM 模型] → 数据库
客户端 ← [Pydantic Schema 序列化] ← 路由函数 ← [ORM 模型] ← 数据库

Основы Pydantic-схем

Pydantic V2 — это движок данных FastAPI, определяющий структуры данных через аннотации типов.

Пример

from pydantic import BaseModel, ConfigDict

class ItemCreate(BaseModel):
    """Схема для создания запросов"""
    name: str
    price: float                       # Автоматически проверять тип
    is_offer: bool = False             # Со значениями по умолчанию (необязательные поля)

class ItemResponse(Base):
    """Ответ"""
    id: int
    name: str
    price: float

    # Подход V2: включить режим ORM, позволяющий прямое преобразование из объектов ORM.
    model_config = ConfigDict(from_attributes=True)

Определите схему для

Пример

# Путь к файлу: schemas.py
from pydantic import BaseModel, ConfigDict
from datetime import datetime
from typing import Optional

# ====== Схема категории ======
class Category(BaseModel):
    name: str
    slug: str

class CategoryResponse(CategoryBase):
    id: int
    model_config = ConfigDict(from_attributes=True)

# ====== Схема поста ======
class PostBase(BaseModel):
    title: str
    slug: str
    summary: Optional[str] = None      # Optional = может быть None
    content: str
    category_id: int

class PostCreate(PostBase):
    """Схема тела запроса для создания статьи."""
    pass                               # Напрямую наследует PostBase, поля идентичны.

class PostUpdate(BaseModel):
    """Обновление статьи (все поля необязательны)"""
    title: Optional[str] = None
    slug: Optional[str] = None
    summary: Optional[str] = None
    content: Optional[str] = None
    category_id: Optional[int] = None

class PostResponse(PostBase):
    """Схема ответа, возвращаемая клиенту."""
    id: int
    created_at: datetime
    updated_at: datetime
    category: CategoryResponse         # Вложенная схема: возвращает информацию о категории

    model_config = ConfigDict(from_attributes=True)
    from_attributes=True сообщает Pydantic: эту схему можно создать из ORM-объектов

В Pydantic V2,model_config = ConfigDict(from_attributes=True)Заменяет тот, что был в V1class Config: orm_mode = TrueЭта конфигурация позволяет напрямую создавать Pydantic-схему из ORM-объектов SQLAlchemy:PostResponse.model_validate(post_orm_obj)。


Использование схем в маршрутах

Пример

# Путь к файлу: routers/posts.py (пример создания POST-маршрута)
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from database import get_db
from models import Post
from schemas import PostCreate, PostResponse

router = APIRouter(prefix="/posts", tags=["Article"])

# После объявления response_model=PostResponse:
# 1. FastAPI автоматически преобразует ORM-объекты в схему (сериализация)
# 2. Документация API автоматически отображает структуру ответа
@router.post("/", response_model=PostResponse, status_code=201)
def create_post(post_data: PostCreate, db: Session = Depends(get_db)):
    """
Создать новую статью
- post_data: тело запроса, FastAPI автоматически валидирует по схеме PostCreate
db: сессия базы данных, внедрённая через Depends(get_db)
    """

    post = Post(**post_data.model_dump())  # model_dump() преобразует схему в dict
    db.add(post)
    db.commit()
    db.refresh(post)                       # Обновить и получить автоинкрементный ID из базы данных
    return post                            # FastAPI автоматически сериализует с помощью PostResponse.

response_modelЭто одна из самых сильных сторон FastAPI. После объявления FastAPI будет: 1. Автоматически отфильтровывать поля из ORM-объектов, которые не объявлены в схеме; 2. Автоматически преобразовывать такие типы, как datetime, в строки JSON; 3. Генерировать точную документацию OpenAPI.


Сравнение ORM-модели и Pydantic-схемы

АспектORM-модель SQLAlchemyPydantic-схема
Место определенияmodels.pyschemas.py
базовый классBase (DeclarativeBase)BaseModel (Pydantic)
ОбязанностиОпределять структуры таблиц базы данных и связиОпределять форматы ввода/вывода API и правила валидации.
Связь с базой данныхНапрямую сопоставляется с таблицами базы данныхОн не заботится о базе данных, только о контракте API.
Объявление поляColumn(Integer, ...)Аннотации типов Python: int, str
сериализацияНевозможно напрямую преобразовать в JSONВстроенные .model_dump() и сериализация JSON
Направление преобразованияORM → Schema: model_validate(obj)Schema → ORM: Model(**schema.model_dump())

Итоги главы

В этой главе вы освоили самые основные концепции Pydantic Schema в FastAPI: BaseModel для определения Schema запросов/ответов, from_attributes=True для включения ORM-режима, response_model для автоматической сериализации ORM-объектов и принцип разделения ответственности между Schema и ORM-моделями.

В этом суть архитектуры FastAPI, управляемой типами: сначала определите форму данных, а маршруты и документация генерируются автоматически.

Другие расширения