Qué es Pydantic?

Pydantic es una librería de Python que permite definir modelos de datos usando clases. Su objetivo principal es validar y convertir datos de forma automática. Está basada en type hints (sugerencia de tipos en Python).

type hints (documentación oficial)

FastAPI la integra de manera nativa:

  • Para definir qué datos recibe un endpoint (entrada).
  • Para definir qué datos devuelve un endpoint (salida).
  • Para generar documentación automática en Swagger UI (/docs).

Ejemplo conceptual

Imaginemos que tu API recibe información de un usuario. En lugar de validar campo por campo manualmente, definís un modelo Pydantic que describe la estructura esperada, y Pydantic se encarga de todo.

Por qué usar Pydantic?

  • Validación automática: si un campo no cumple con el tipo o las restricciones, lanza un error.
  • Conversión automática (type coercion): intenta transformar los datos al tipo correcto si es posible.
  • Valores por defecto: permite inicializar campos automáticamente.
  • Documentación clara: cada modelo sirve como contrato de datos para tu API.
  • Integración con FastAPI: lo que definís en el modelo aparece automáticamente en /docs.

Definiendo un modelo simple

from pydantic import BaseModel

class Usuario(BaseModel):
    id: int
    nombre: str
    email: str
    activo: bool = True  # Valor por defecto

Qué hace este modelo?

  • id debe ser un número entero.
  • nombre debe ser un texto.
  • email debe ser un texto.
  • activo es un booleano, y si no se envía, por defecto es True.

Usando el modelo en Python (podemos usar Pydantic sin FastAPI), por ejemplo ejecutar:

usuario1 = Usuario(id=1, nombre="Diego", email="diego@test.com")
print(usuario1)

# Salida:
# id=1 nombre='Diego' email='diego@test.com' activo=True

# Si enviamos datos incorrectos:
usuario2 = Usuario(id="uno", nombre="Diego", email="diego@test.com")

# Error:
# pydantic.error_wrappers.ValidationError: 1 validation error for Usuario
# id
#   value is not a valid integer (type=type_error.integer)
Validación con Pydantic - ejemplo de error

Conversión automática

Pydantic puede convertir datos si son compatibles:

usuario1 = Usuario(id="2", nombre="María", email="maria@test.com")
print(usuario1.id, type(uusuario1.id))  # 2 <class 'int'>

Valores por defecto y opcionales

Podemos definir campos opcionales con None y dar valores iniciales:

from typing import Optional

class Usuario(BaseModel):
    id: int
    nombre: str
    email: Optional[str] = None
    activo: bool = True

Aquí:

  • email puede omitirse: por defecto será None.
  • activo será True si no se envía.

Validaciones adicionales con Field

Field permite agregar restricciones, descripciones y ejemplos.

from pydantic import BaseModel, Field

class Producto(BaseModel):
    codigo: int = Field(gt=0, description="Debe ser un número positivo")
    descripcion: str = Field(min_length=3, max_length=100)
    precio: float = Field(gt=0, description="Precio mayor que 0", example=150.0)

Validaciones:

  • gt=0: el código y precio deben ser mayores que 0.
  • min_length / max_length: controlan la longitud de texto.
  • example: se muestra en la documentación automática de FastAPI.

Métodos útiles de Pydantic

p = Producto(codigo=1, descripcion="Teclado", precio=50.0)

# Convertir a diccionario
print(p.dict())

# Convertir a JSON
print(p.json())

# Acceder como atributos
print(p.codigo, p.descripcion)

# Salida (ejemplo):
# {"codigo": 1, "descripcion": "Teclado", "precio": 50.0}

Ejemplo aplicado en FastAPI

Archivo main.py:

from fastapi import FastAPI
from pydantic import BaseModel, Field

app = FastAPI()

class Producto(BaseModel):
    codigo: int = Field(gt=0, description="Número positivo")
    descripcion: str = Field(min_length=3, max_length=100)
    precio: float = Field(gt=0, description="Precio mayor que 0")

@app.post("/productos/")
def crear_producto(producto: Producto):
    return {
        "mensaje": "Producto creado correctamente",
        "datos": producto
    }

Probar en Swagger UI (/docs):

Enviar este JSON en POST /productos/:

{
  "codigo": 1,
  "descripcion": "Monitor",
  "precio": 250.5
}

# Respuesta:
{
  "mensaje": "Producto creado correctamente",
  "datos": {
    "codigo": 1,
    "descripcion": "Monitor",
    "precio": 250.5
  }
}

Errores automáticos de validación

Si enviamos un JSON inválido:

{
  "codigo": -5,
  "descripcion": "A",
  "precio": -10
}

# FastAPI responde automáticamente con:
{
  "detail": [
    {"loc": ["body","codigo"], "msg": "ensure this value is greater than 0", "type": "value_error.number.not_gt"},
    {"loc": ["body","descripcion"], "msg": "ensure this value has at least 3 characters", "type": "value_error.any_str.min_length"},
    {"loc": ["body","precio"], "msg": "ensure this value is greater than 0", "type": "value_error.number.not_gt"}
  ]
}

# No hace falta escribir validaciones manuales!

Conclusión

  • Pydantic convierte las type hints en validaciones reales.
  • Permite definir modelos limpios y reutilizables.
  • FastAPI aprovecha estos modelos para validar request y response, y generar documentación automática.
  • Con Pydantic, tu API es más robusta, clara y segura.