Los DTOs¶
Por cada tabla se generan varios modelos Pydantic 2. Son objetos normales, sin sesión detrás: se
pueden serializar, devolver desde una API y guardar sin miedo a un DetachedInstanceError.
| DTO | Para qué |
|---|---|
<Modelo>Read |
Lo que devuelven las lecturas. Incluye las relaciones cargadas |
<Modelo>Create |
Datos de alta. Admite relaciones anidadas |
<Modelo>Filter |
Filtros; cuáles, según el tipo de cada columna |
<Modelo>UpdateValues |
Los valores a escribir en un update |
<Modelo>Update |
filter + values, para update_many |
<Modelo>UpdateNested |
Actualización de una relación anidada |
<Modelo>DataFrameValidator |
Valida un DataFrame contra el esquema de la tabla |
Read¶
usuario = public_sync_api.usuario.find(id=1, includes=['posts'])
usuario.nombre # los campos, tipados
usuario.posts # List[PostRead], si se pidió en includes
usuario.model_dump() # dict
usuario.model_dump_json() # str
usuario.to_dict() # dict, omitiendo los None
Incluye las columnas calculadas y las columnas de auditoría, si el schema las declara. Las columnas cifradas vienen descifradas y las vectoriales solo si se pidieron.
Create¶
UsuarioCreate(nombre='Ana', email='ana@x.com')
PostCreate(
titulo='Hola',
contenido='...',
autor=UsuarioCreate(nombre='Ana', email='ana@x.com'), # relación anidada
)
Las columnas con default, las opcionales y las autoincrementales no hacen falta. Los campos
que no existen en la tabla se rechazan (extra='forbid'): un typo en el nombre de un campo
es un error de validación, no un valor que se pierde en silencio.
Filter y Update¶
from database.public import UsuarioFilter, UsuarioUpdateValues, UsuarioUpdate
public_sync_api.usuario.update_many(UsuarioUpdate(
filter=UsuarioFilter(activo=False, min_creado_en=datetime(2026, 1, 1)),
values=UsuarioUpdateValues(activo=True),
))
UpdateValues solo lleva lo que quieras escribir: lo que no declares no se toca.
Enumerados¶
Los campos de tipo enumerado se validan contra sus valores:
PostCreate(titulo='Hola', contenido='...', estado='publicado') # ✅
PostCreate(titulo='Hola', contenido='...', estado='inventado') # ValidationError
Y los valores posibles se consultan en la fachada:
Usarlos con FastAPI¶
Son modelos Pydantic estándar, así que encajan directamente:
from fastapi import FastAPI
from database.public import public_sync_api, UsuarioRead, UsuarioCreate
app = FastAPI()
@app.get('/usuarios', response_model=list[UsuarioRead])
def listar(limit: int = 50):
return public_sync_api.usuario.find_many(limit=limit)
@app.post('/usuarios', response_model=UsuarioRead)
def crear(usuario: UsuarioCreate):
return public_sync_api.usuario.create(usuario)