Pydantic Schema — Validación y serialización de datos
En este capítulo aprenderás Pydantic Schema, entenderás su separación de responsabilidades con el modelo ORM, que es la característica más central de FastAPI.
¿Por qué necesitamos un Schema?
El modelo ORM (models.py) define la estructura de la base de datos, pero no se puede usar directamente para la validación de solicitudes/respuestas de la API.
Razón: el modelo ORM contiene lógica específica de la base de datos (como relationship), y no se desea exponer todos los campos a la API.
Pydantic SchemaEs una clase de datos pura, dedicada a la validación y serialización de entrada/salida de la API.
La relación entre estos tres:
客户端 → [Pydantic Schema 校验] → 路由函数 → [ORM 模型] → 数据库 客户端 ← [Pydantic Schema 序列化] ← 路由函数 ← [ORM 模型] ← 数据库
Fundamentos de Pydantic Schema
Pydantic V2 es el motor de datos de FastAPI, define estructuras de datos mediante sugerencias de tipo.
Ejemplo
class ItemCreate(BaseModel):
"""Crear el Schema de la solicitud"""
name: str
price: float # Validar tipos automáticamente
is_offer: bool = False # Con valor predeterminado (campo opcional)
class ItemResponse(BaseModel):
"""Schema de respuesta"""
id: int
name: str
price: float
# Sintaxis V2: activar el modo ORM, permite convertir directamente desde objetos ORM
model_config = ConfigDict(from_attributes=True)
Definir el Schema del blog
Ejemplo
from pydantic import BaseModel, ConfigDict
from datetime import datetime
from typing import Optional
# ====== Category Schema ======
class CategoryBase(BaseModel):
name: str
slug: str
class CategoryResponse(CategoryBase):
id: int
model_config = ConfigDict(from_attributes=True)
# ====== Post Schema ======
class PostBase(BaseModel):
title: str
slug: str
summary: Optional[str] = None # Optional = puede ser None
content: str
category_id: int
class PostCreate(PostBase):
"""Schema del cuerpo de la solicitud al crear un artículo"""
pass # Hereda directamente de PostBase, campos idénticos
class PostUpdate(BaseModel):
"""Actualizar artículo (todos los campos opcionales)"""
title: Optional[str] = None
slug: Optional[str] = None
summary: Optional[str] = None
content: Optional[str] = None
category_id: Optional[int] = None
class PostResponse(PostBase):
"""Schema de respuesta devuelto al cliente"""
id: int
created_at: datetime
updated_at: datetime
category: CategoryResponse # Schema anidado: devolver información de la categoría
model_config = ConfigDict(from_attributes=True)
# from_attributes=True le dice a Pydantic: este Schema se puede crear desde un objeto ORM
En Pydantic V2,
model_config = ConfigDict(from_attributes=True)reemplaza al de V1class Config: orm_mode = True. Esta configuración te permite construir un Pydantic Schema directamente desde un objeto SQLAlchemy ORM:PostResponse.model_validate(post_orm_obj)。
Usar Schema en las rutas
Ejemplo
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=["Artículo"])
# Después de declarar response_model=PostResponse:
# 1. FastAPI convierte automáticamente el objeto ORM a Schema (serialización)
# 2. El documento de la API muestra automáticamente la estructura de la respuesta
@router.post("/", response_model=PostResponse, status_code=201)
def create_post(post_data: PostCreate, db: Session = Depends(get_db)):
"""
Crear nuevo artículo
- post_data: cuerpo de la solicitud, FastAPI lo valida automáticamente según el Schema PostCreate
- db: sesión de base de datos inyectada mediante Depends(get_db)
"""
post = Post(**post_data.model_dump()) # model_dump() convierte el Schema a diccionario
db.add(post)
db.commit()
db.refresh(post) # Refrescar, obtener el ID autoincremental de la base de datos
return post # FastAPI serializa automáticamente con PostResponse
response_modelEs una de las características más potentes de FastAPI. Tras declararlo, FastAPI: 1. Filtra automáticamente los campos del objeto ORM que no están declarados en el Schema; 2. Convierte automáticamente tipos como datetime a cadenas JSON; 3. Genera documentación OpenAPI precisa.
Comparación entre modelo ORM y Pydantic Schema
| Aspecto | Modelo SQLAlchemy ORM | Pydantic Schema |
|---|---|---|
| Ubicación de definición | models.py | schemas.py |
| Clase base | Base (DeclarativeBase) | BaseModel (Pydantic) |
| Responsabilidad | Define la estructura y relaciones de las tablas de la base de datos | Define los formatos de entrada/salida de la API y las reglas de validación |
| Relación con la base de datos | Mapea directamente las tablas de la base de datos | No le importa la base de datos, solo el contrato de la API |
| Declaración de campos | Column(Integer, ...) | Sugerencias de tipo de Python: int, str |
| Serialización | No se puede convertir directamente a JSON | Incorpora .model_dump() y serialización JSON |
| Dirección de conversión | ORM → Schema:model_validate(obj) | Schema → ORM:Model(**schema.model_dump()) |
Resumen del capítulo
En este capítulo has dominado el Pydantic Schema más central de FastAPI: BaseModel define los Schemas de solicitud/respuesta, from_attributes=True activa el modo ORM, response_model serializa automáticamente los objetos ORM, y el principio de separación de responsabilidades entre Schema y modelo ORM.
Este es el núcleo de la arquitectura impulsada por tipos de FastAPI: primero define la forma de los datos, y las rutas y la documentación se generan automáticamente.
Otras extensiones