Volver al catálogo
Season 9 20 Episodios 1h 20m 2026

Pydantic: Data Validation

v2.12 — Edición 2026. Un análisis en profundidad de Pydantic v2.12, la biblioteca de validación de datos más utilizada para Python, desde su uso básico hasta funciones avanzadas como core schemas personalizados y la observabilidad con Logfire.

Validación de datos Python Core
Pydantic: Data Validation
Reproduciendo ahora
Click play to start
0:00
0:00
1
La filosofía de Pydantic: Type Hints como validación
Este episodio presenta la premisa fundamental de Pydantic. Aprenderás cómo se pueden usar los type hints de Python para aplicar esquemas y cómo el core en Rust impulsa inmensas mejoras de rendimiento.
3m 55s
2
La anatomía de un BaseModel
Sumérgete en BaseModel, la abstracción fundamental de Pydantic. Aprenderás cómo la instanciación valida los datos, cómo se realiza la coerción de los campos y cómo se muestran los errores de validación.
3m 47s
3
Restricciones de campos y el patrón Annotated
Aprende a imponer límites más allá de los tipos básicos. Descubrirás cómo usar la función Field y el constructor de tipado Annotated para añadir restricciones como mínimos y longitudes máximas.
4m 32s
4
Alias de campos para validación y serialización
Resuelve el conflicto de convenciones de nomenclatura entre las APIs externas y el código interno de Python. Aprenderás a desacoplar los nombres de tus atributos de Python de las claves JSON utilizando alias de validación y serialización.
3m 59s
5
Coerción de datos vs Strict Mode
Toma el control de la tendencia de Pydantic a la coerción de datos. Aprenderás a forzar coincidencias de tipo exactas activando el Strict Mode a nivel de campo o de modelo.
4m 37s
6
Observabilidad en el mundo real con Logfire
Aporta transparencia a tus pipelines de datos. Aprenderás a integrar Pydantic con Logfire para monitorizar las validaciones exitosas y fallidas en tiempo real.
4m 17s
7
Validación de tipos arbitrarios con TypeAdapter
Aprende a validar primitivas independientes y listas sin crear un BaseModel. Descubrirás cómo TypeAdapter convierte cualquier tipo de Python en un objetivo de validación de pleno derecho.
3m 07s
8
Tipos Union y validación inteligente
Entiende las complejidades de la validación de tipos Union. Aprenderás cómo el Smart Mode de Pydantic evalúa la exactitud y los campos válidos para elegir la mejor coincidencia.
4m 03s
9
Herramienta avanzada: Discriminated Unions
Potencia el rendimiento de tu validación. Aprenderás a usar Discriminated (Tagged) Unions para decirle a Pydantic exactamente qué esquema aplicar basándose en un campo específico.
3m 48s
10
Preprocesamiento con Before Validators y Wrap Validators
Maneja datos entrantes desordenados antes de que lleguen a tu esquema. Aprenderás a usar los validadores de campo Before y Wrap para limpiar la entrada en bruto antes de que Pydantic la evalúe.
4m 19s
11
Postprocesamiento con After Validators y Plain Validators
Aplica reglas estrictas de lógica de negocio. Aprenderás a usar After Validators para verificar datos ya parseados, y Plain Validators para cortocircuitar Pydantic por completo.
3m 33s
12
Hooks de validación a nivel de modelo
Valida interacciones a través de múltiples campos. Aprenderás a usar el decorador model_validator para aplicar reglas que dependen de todo el payload.
3m 57s
13
Serialización: Volcando datos de forma segura
Controla cómo salen tus datos del sistema. Aprenderás las diferencias entre volcar a dicts de Python frente a cadenas JSON, y cómo excluir campos no establecidos o por defecto.
4m 02s
14
Personalizando la lógica de serialización
Cambia cómo se representan tus tipos a la salida. Aprenderás a escribir serializadores personalizados de Field y Model para mutar los datos durante la fase de volcado.
3m 27s
15
Generando JSON Schema a partir de modelos
Convierte tus modelos en contratos de API autodocumentados. Aprenderás a generar JSON Schemas compatibles con OpenAPI e inyectar ejemplos directamente en el esquema.
4m 28s
16
RootModel: Cuando tu payload no es un diccionario
Maneja payloads JSON no estándar con elegancia. Descubrirás cómo RootModel te permite parsear arrays y primitivas a nivel raíz mientras conservas los poderes de BaseModel.
3m 24s
17
Dataclasses estándar vs Dataclasses de Pydantic
Lleva la validación a tus clases nativas de Python. Aprenderás cuándo usar el decorador dataclass de Pydantic para modernizar bases de código heredadas sin reescribir todo.
4m 22s
18
Ajuste fino de la configuración del modelo
Controla el rigor de todo tu modelo. Aprenderás a usar el ConfigDict para prohibir atributos adicionales, congelar instancias y validar asignaciones.
3m 51s
19
Configuración de aplicaciones con Pydantic Settings
Gestiona tus variables de entorno como un profesional. Aprenderás cómo el paquete pydantic-settings automatiza el parseo de secretos, archivos dot-env y prefijos.
4m 13s
20
Bajo el capó: Core Schemas personalizados
¡Este es el episodio final de la serie! Toma el control absoluto del motor de validación. Aprenderás a escribir un método __get_pydantic_core_schema__ para enseñar al core en Rust cómo manejar objetos de Python completamente ajenos.
4m 31s

Episodios

1

La filosofía de Pydantic: Type Hints como validación

3m 55s

Este episodio presenta la premisa fundamental de Pydantic. Aprenderás cómo se pueden usar los type hints de Python para aplicar esquemas y cómo el core en Rust impulsa inmensas mejoras de rendimiento.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Validación de datos, episodio 1 de 20. La mayoría de las librerías de validación de datos te obligan a aprender un domain-specific language completamente nuevo solo para definir un schema. Pero, ¿y si la sintaxis built-in de Python ya fuera suficiente para aplicar tus reglas? La filosofía de Pydantic: Type Hints como validación, resuelve precisamente esta tensión. Antes de ver cómo funciona, debemos aclarar una confusión común. Pydantic no es un static type checker como mypy. Mypy analiza tu código fuente antes de ejecutarlo para detectar errores lógicos. Pydantic opera en runtime. Toma datos no fiables del mundo exterior, como un payload JSON de una API request, y los obliga a ajustarse a los tipos que definiste, justo cuando tu programa se está ejecutando. La filosofía central aquí es la simplicidad. Defines un modelo de datos usando type annotations estándar de Python. Creas una clase que representa a un usuario, y especificas que el user ID es un integer, y la fecha de registro es un objeto datetime. Ese es todo tu schema. No escribes funciones de validación personalizadas ni importas field types propietarios. Cuando llega un diccionario desordenado desde un formulario web, simplemente se lo pasas a tu clase. Pydantic lo intercepta y garantiza que el objeto resultante se adhiera estrictamente a esos tipos. Aquí está la clave. Pydantic es fundamentalmente una librería de parsing, no solo una barrera de validación estricta. Si un usuario envía un formulario web donde el user ID es el string cuarenta y dos, Pydantic reconocerá que tu modelo espera un integer. Convierte automáticamente ese string en un integer nativo de Python. Intenta que los datos encajen en tu schema antes de lanzar un error. Esto se encarga del tedioso data coercion, para que no tengas que escribir lógica de parsing manual para cada input field. Validar y convertir cada dato entrante en runtime suena inherentemente lento, especialmente en Python. Para solucionar esto, la lógica de ejecución en realidad no corre en Python. Pydantic delega el trabajo pesado a un core engine dedicado, escrito completamente en Rust. Este diseño te da la developer experience rápida de escribir Python puro, combinada con la velocidad de ejecución bruta del código de sistema compilado. Imagina una background task parseando un archivo JSON enorme donde cada registro contiene una dirección web. Si escribes código Python puro para iterar sobre miles de diccionarios, extraer cada string, cargar una librería de expresiones regulares y verificar que cada string sea una URL válida, tu proceso se arrastrará. Pydantic gestiona esto sin problemas. Simplemente anotas el campo de dirección como un tipo URL y le pasas el raw JSON a tu modelo. El motor de Rust vuela a través del texto, parseando y validando los formatos a velocidades que el Python nativo no puede igualar. El verdadero poder de este enfoque es que el autocomplete de tu editor, tus herramientas de análisis estático y tu validación en runtime comparten exactamente la misma source of truth, que son tus type hints estándar. Si estos episodios te resultan útiles y quieres apoyar el programa, puedes buscar DevStoriesEU en Patreon. Eso es todo por este episodio. ¡Gracias por escuchar y sigue construyendo!
2

La anatomía de un BaseModel

3m 47s

Sumérgete en BaseModel, la abstracción fundamental de Pydantic. Aprenderás cómo la instanciación valida los datos, cómo se realiza la coerción de los campos y cómo se muestran los errores de validación.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Validación de datos, episodio 2 de 20. A menudo hablamos de validación de datos, pero si observas Pydantic con atención, su objetivo principal es en realidad la coerción. Garantiza la estructura de tu output, no de tu input. La anatomía de un BaseModel es lo que hace posible esta distinción. La clase BaseModel es la base de Pydantic. Para definir un schema, creas una clase estándar de Python y heredas de BaseModel. Una vez que haces eso, Pydantic transforma tu clase en un contenedor de datos estricto. Defines la forma de tus datos usando type hints estándar de Python. No necesitas funciones propietarias para declarar un string o un número. Simplemente escribes el nombre del atributo, dos puntos y el tipo de Python esperado. Considera un modelo User. Dentro de la clase, defines un único campo llamado id, y lo tipas como un integer. También podrías añadir un campo name tipado como un string. Esa es toda la definición. Aquí está la clave. El trabajo real ocurre en el momento en que instancias el modelo. Creas una instancia pasando tus datos como keyword arguments, haciendo coincidir los nombres de los campos que definiste. Cuando haces esto, Pydantic intercepta los datos antes de que el objeto esté completamente inicializado. Compara los valores entrantes con tus type hints. Aquí es donde ocurre la coerción. Si pasas el integer uno dos tres al campo id, Pydantic lo acepta inmediatamente. Pero supón que estás recibiendo datos de una web request o de un archivo de texto, y pasas el string "123" exactamente a ese mismo campo. Pydantic no lanza un error al instante. Reconoce que el tipo de destino es un integer e intenta convertir el string. Como los caracteres se pueden castear de forma segura a un número, Pydantic realiza la conversión silenciosamente. El objeto se crea, y el campo id almacena un verdadero integer de Python, no un string. Este comportamiento demuestra que Pydantic es esencialmente una librería de parsing. Transforma los datos entrantes para que encajen en el schema estricto que definiste. Por supuesto, esta conversión tiene límites lógicos. Si instancias el modelo User y pasas el string "not an int" al campo id, Pydantic intenta la conversión y falla. Cuando la coerción es imposible, Pydantic lanza un ValidationError. Este error detiene la ejecución inmediatamente. Un detalle crucial sobre el ValidationError es que Pydantic evalúa todos los campos antes de lanzarlo. Si tu modelo tiene varios campos con datos no válidos, la excepción contendrá los detalles de todos los fallos, en lugar de detenerse en el primer error. El error señala los campos exactos que causaron el problema, los valores específicos proporcionados y las razones por las que falló el parsing. Una vez que tus datos pasan la instanciación con éxito, el objeto resultante tiene la garantía de coincidir con tus type hints. Accedes a los datos exactamente igual que a cualquier objeto estándar de Python, usando dot notation. Si asignaste la instancia a una variable llamada user, simplemente escribes user punto id para recuperar el integer. No se requieren métodos getter ni setter. Estás interactuando con un objeto limpio y fuertemente tipado. El verdadero valor de heredar de BaseModel no es solo que rechaza malos inputs, sino que normaliza de forma segura datos externos impredecibles hacia un estado interno altamente predecible. Gracias por escuchar. Cuidaos todos.
3

Restricciones de campos y el patrón Annotated

4m 32s

Aprende a imponer límites más allá de los tipos básicos. Descubrirás cómo usar la función Field y el constructor de tipado Annotated para añadir restricciones como mínimos y longitudes máximas.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Data Validation, episodio 3 de 20. Los type hints estándar te dicen que un field es un integer, pero no te pueden decir que tiene que ser mayor que cero. Cuando una edad negativa o un username de diez mil caracteres se cuela en los límites de tu aplicación, el type checking básico ya no es suficiente para proteger tu backend. Para aplicar límites estrictos a tus datos, necesitas Field Constraints y el Annotated Pattern. En Pydantic, los constraints te permiten restringir los valores permitidos para un tipo específico. En lugar de escribir funciones validator personalizadas para cada regla menor, puedes definir límites matemáticos o estructurales directamente en el field. Para tipos numéricos, puedes aplicar límites de mayor o menor que usando parámetros como g-t y l-t. Para strings, puedes restringir el tamaño del input usando max length y min length. Para aplicar estas reglas, Pydantic proporciona una utility function llamada Field. La forma tradicional en que los developers aplicaban estos constraints era asignando una llamada a la función Field como valor por defecto de un atributo del model. Por ejemplo, declararías un atributo age, le pondrías un type hint de integer, y lo igualarías a Field, pasándole g-t igual a cero. Esta estructura funciona, pero introduce fricción. Si necesitas un integer positivo en quince models diferentes, estás escribiendo esa misma asignación de Field quince veces. Peor aún, como la función Field ocupa el espacio de asignación del valor por defecto en el model, complica las cosas cuando realmente quieres asignar un integer por defecto real a ese atributo. Aquí está la clave. No tienes que vincular tus reglas de validación a la asignación del atributo para nada. Puedes integrarlas directamente en la propia definición del tipo usando typing dot Annotated de Python. Annotated es una feature de la standard library que te permite adjuntar metadatos arbitrarios a un type hint base. Pydantic está diseñado específicamente para mirar dentro de un tipo Annotated, encontrar cualquier función Field que hayas proporcionado, y extraer sus reglas de validación automáticamente. Cuando usas Annotated, le pasas dos datos distintos. Primero, proporcionas el tipo base de Python, como un integer o un string. Segundo, proporcionas los metadatos, que en nuestro caso es la función Field de Pydantic que contiene tus constraints. Vamos a crear un tipo age reutilizable para ver cómo fluye esto. Defines una nueva variable en tu código llamada PositiveInt. La asignas a Annotated. Dentro de Annotated, pasas integer como tipo base, seguido de una coma, y luego la función Field con g-t igual a cero. Acabas de crear un type constraint personalizado y reutilizable. Ahora, cada vez que definas un user model o un employee model, simplemente le pones el type hint a tu field age con PositiveInt. No necesitas llamar a la función Field en el atributo del model. Este enfoque separa tus definiciones de tipos de las estructuras de tus models. Tus models se mantienen increíblemente limpios, leyéndose justo como clases estándar de Python sin desorden. Si tu lógica de negocio cambia más adelante y de repente necesitas que un field age sea mayor que dieciocho en lugar de cero, actualizas la definición de PositiveInt en exactamente un solo lugar. Ese constraint actualizado se aplica instantáneamente a cada model que lo utiliza. Además, como Annotated es una feature nativa de Python, los static type checkers entienden perfectamente que tu PositiveInt personalizado se evalúa finalmente como un integer estándar. Al desacoplar los metadatos de validación del espacio del valor por defecto, el Annotated pattern transforma los field constraints de boilerplate repetitivo a una librería compartida de domain types estrictos y reutilizables. Gracias por pasar unos minutos conmigo. Hasta la próxima, cuídate.
4

Alias de campos para validación y serialización

3m 59s

Resuelve el conflicto de convenciones de nomenclatura entre las APIs externas y el código interno de Python. Aprenderás a desacoplar los nombres de tus atributos de Python de las claves JSON utilizando alias de validación y serialización.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Data Validation, episodio 4 de 20. ¿Alguna vez te has visto obligado a nombrar una variable de Python en camel case solo para parsear el payload de una API externa? Sabes que rompe las convenciones de nomenclatura estándar de Python, pero el JSON entrante dicta la key. La solución a esto son los Field Aliases para validación y serialización. Cuando ingieres datos, las keys de ese payload a menudo no coinciden con cómo quieres estructurar tu código Python. Si un servicio de terceros envía un perfil de usuario con la key user N mayúscula name, quieres mapear eso a una variable estándar en snake case llamada user guion bajo name. Pydantic gestiona esta capa de traducción usando la función Field, específicamente a través de sus argumentos alias. El enfoque más simple es el argumento alias base. Cuando declaras el atributo de tu modelo, le asignas un Field y configuras el parámetro alias con el string que esperas del mundo exterior. Si configuras el alias con la versión en camel case, Pydantic usa ese string exacto tanto para leer como para escribir. Al validar los datos entrantes, busca la key en camel case. Cuando más tarde serializas el modelo para hacer un dump de vuelta a JSON, escribe la key en camel case. Tu código Python interno opera completamente sobre el atributo en snake case, totalmente aislado de la convención de nomenclatura externa. Eso cubre los datos simétricos, donde el formato de entrada y el formato de salida son idénticos. Ahora, la segunda parte de esto son los datos asimétricos. ¿Qué pasa cuando consumes datos de un sistema legacy usando una convención de nomenclatura, pero necesitas servirlos a un nuevo cliente usando otra? Aquí es donde divides la lógica usando validation aliases y serialization aliases. Estos son argumentos separados que le pasas a la función Field. Un validation alias dicta estrictamente qué busca Pydantic al crear el modelo. Si proporcionas un validation alias, Pydantic lo usará para sacar el valor del payload entrante, sobrescribiendo cualquier alias base que hayas configurado. Por el contrario, un serialization alias controla solo la fase de salida. Cuando llamas a un método para hacer un dump del modelo a un dictionary o a un string JSON, Pydantic usa el serialization alias como la key de salida. Aquí está el punto clave. Puedes definir un solo field con tres identidades distintas. El validation alias captura el string de entrada desordenado de la API legacy. El atributo de Python guarda la variable limpia en snake case que usas en tu lógica de negocio. Finalmente, el serialization alias define la key pulida y estandarizada que se envía a tu frontend. A veces el problema no es una convención de nomenclatura rígida, sino una inconsistente. Puedes recibir payloads donde el identificador de usuario a veces está en camel case y a veces es una sola palabra sin espacios. Para manejar esto, Pydantic proporciona una utilidad llamada Alias Choices. En lugar de pasar un solo string al validation alias, pasas esta utilidad que contiene una lista de strings. Durante la validación, Pydantic escanea el payload entrante en busca de cada string en el orden que proporcionaste. En el momento en que encuentra una key coincidente, extrae el valor, lo asigna a tu atributo de Python e ignora el resto. Al separar cómo se parsean los datos de cómo se exportan, los alias desacoplan el diseño interno de tu objeto Python de las restricciones de nomenclatura arbitrarias del mundo exterior. Eso es todo por este episodio. Gracias por escuchar, ¡y sigue programando!
5

Coerción de datos vs Strict Mode

4m 37s

Toma el control de la tendencia de Pydantic a la coerción de datos. Aprenderás a forzar coincidencias de tipo exactas activando el Strict Mode a nivel de campo o de modelo.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Validación de datos, episodio 5 de 20. Las ganas que tiene Pydantic de convertir el string "123" en un integer es una killer feature, justo hasta que oculta silenciosamente un bug de tipo de datos en tu payload JSON. Esperas números, recibes strings, y tu aplicación sigue adelante sin problemas hasta que un sistema downstream estricto crashea. El mecanismo que controla este comportamiento es la Data Coercion, y para domarlo necesitas entender el Strict Mode. Por defecto, Pydantic opera en lo que la documentación llama lax mode. En este modo, Pydantic actúa como un parser de datos más que como un simple type checker. Intenta activamente hacer coerción, o convertir, los datos entrantes al tipo que has declarado. Si defines un campo como un integer, y el payload de entrada trae el string "123", Pydantic evalúa el string, extrae el número válido y lo transforma en un integer real. Este comportamiento es increíblemente útil cuando procesas el input del usuario desde formularios web o query parameters, donde cada valor entrante es, fundamentalmente, un string. Sin embargo, cuando estás construyendo APIs machine-to-machine, la conversión silenciosa suele ser peligrosa. Si un cliente promete enviar un integer pero en su lugar envía un string, está rompiendo el contrato de la API. El lax mode oculta esta violación. Aquí es donde entra en juego el strict mode. El strict mode desactiva la coerción automática de tipos. Cuando lo activas, Pydantic exige que el tipo de dato entrante coincida exactamente con tu type annotation. Pásale el string "123" a un campo integer estricto, y Pydantic lo rechazará inmediatamente con un error de validación. Esto obliga a la fuente de datos a respetar el schema. Tienes dos formas de aplicar el strict mode: globalmente en todo un modelo, o localmente en campos específicos. Para forzarlo globalmente, modificas la configuración del modelo. Al poner el flag de configuración strict en true, todos y cada uno de los campos de ese modelo dejan de hacer coerción de tipos. Un campo booleano solo aceptará un valor booleano true o false, no el string "true" ni el integer 1. Un campo integer solo aceptará integers. Aquí está la clave. La rigidez global suele ser excesiva para aplicaciones del mundo real donde los datos llegan de fuentes mixtas. Normalmente quieres blindar unos pocos identificadores críticos mientras dejas el resto del modelo flexible. Para lograr esto, Pydantic permite la rigidez local. Puedes forzar el strict mode en un campo individual usando tipos especializados que proporciona la librería, como StrictInt, StrictStr o StrictBool. Si defines un campo de ID de usuario usando StrictInt, ese campo en concreto rechazará las representaciones en string de los números, mientras que el resto de tu modelo seguirá operando en lax mode. También puedes lograr esto pasándole un flag strict directamente a la función de definición del campo para cualquier tipo estándar. Imagina un servicio que procesa un payload JSON para una transacción financiera. El payload contiene un ID de cuenta. Si lo defines como un integer normal, un payload que envíe el ID de cuenta como el string "123" pasará sin problemas. Pydantic arregla el tipo de dato en memoria. Si actualizas ese campo para usar StrictInt, exactamente el mismo payload JSON fallará la validación. El cliente recibe un error explícito indicando que el input debe ser un integer válido, cazando la violación del contrato en la frontera del sistema antes de que contamine tu base de datos. El strict mode transforma a Pydantic, pasando de ser un parser útil que limpia inputs desordenados a un guardián rígido que garantiza los contratos de datos. Gracias por escuchar. Cuidaos todos.
6

Observabilidad en el mundo real con Logfire

4m 17s

Aporta transparencia a tus pipelines de datos. Aprenderás a integrar Pydantic con Logfire para monitorizar las validaciones exitosas y fallidas en tiempo real.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Validación de datos, episodio 6 de 20. Cuando un payload complejo falla la validación en producción, el stack trace estándar por sí solo rara vez te dice exactamente por qué se rechazaron los datos. Sabes que una request falló, pero estás completamente a ciegas sobre los valores de entrada reales que están causando el crash. Ese es exactamente el problema que resuelve la observabilidad en el mundo real con Logfire. Logfire es una plataforma de observabilidad creada por el equipo de Pydantic, y cuenta con integración directa con el propio Pydantic. El objetivo es darte visibilidad sobre lo que tu capa de validación de datos está haciendo realmente en producción. En lugar de tratar la validación como una caja negra que de vez en cuando lanza excepciones, esta integración convierte cada comprobación de validación en telemetría rastreada. Imagina un background worker procesando registros de usuarios desde una message queue. Llegan cientos de eventos por segundo. De repente, un registro falla con un error de validación. Sin la instrumentación adecuada, tus logs muestran un crash genérico. Tienes que rebuscar en el payload en crudo de la queue para descubrir que el usuario introdujo una edad de menos cinco. Para solucionar esto, importas el paquete Logfire y llamas a una única función llamada instrument underscore pydantic. Lo colocas justo después de inicializar tu cliente de Logfire. A partir de ese momento, tus modelos de Pydantic son completamente observables. No necesitas cambiar cómo defines tus modelos ni cómo los instancias. Aquí está la clave. Una vez instrumentado, cada vez que Pydantic valida datos, Logfire crea automáticamente un span. Un span es simplemente un registro cronometrado de una operación. Si el payload de registro es perfectamente válido, Logfire registra un span exitoso que muestra exactamente cuánto tiempo tardó la validación. Esto es muy útil si tienes validadores personalizados complejos y necesitas monitorizar cuellos de botella de rendimiento. Si el payload es inválido, Pydantic lanza un error de validación. Logfire captura este evento y adjunta los detalles al trace. Captura el modelo específico involucrado y los campos exactos que provocaron el fallo. Cuando miras tu dashboard de observabilidad, no ves solo un mensaje de error genérico. Ves los valores rechazados exactos, como esa edad negativa o un string de email mal formado. La configuración es totalmente automática. Primero, configura el cliente. Segundo, llama a la función instrument. Tercero, deja que tu worker procese datos. Cuando el worker intenta parsear un string JSON incorrecto en tu modelo de registro, la telemetría captura el contexto del fallo automáticamente. Escribes absolutamente cero bloques de excepciones personalizados para loguear el input incorrecto. Como Logfire entiende Pydantic de forma nativa, respeta tus estructuras de datos. Conoce la diferencia entre un campo faltante y un type mismatch, y formatea esa telemetría para que puedas hacerle queries más tarde. Puedes filtrar tus métricas para descubrir exactamente cuántas veces falló la validación del campo email en todo tu cluster de workers hoy. El verdadero valor de esta integración es que eleva la validación de datos de un simple code check a un evento de observabilidad de primer nivel, transformando los rechazos de datos silenciosos en telemetría estructurada y accionable. Si quieres apoyar el programa, puedes encontrarnos buscando DevStoriesEU en Patreon. Eso es todo por este episodio. Gracias por escuchar, ¡y sigue construyendo!
7

Validación de tipos arbitrarios con TypeAdapter

3m 07s

Aprende a validar primitivas independientes y listas sin crear un BaseModel. Descubrirás cómo TypeAdapter convierte cualquier tipo de Python en un objetivo de validación de pleno derecho.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Validación de datos, episodio 7 de 20. A veces solo necesitas validar una simple lista de strings que viene de una request de una API, pero crear una clase model entera solo para guardar esa única lista parece una exageración. No quieres un objeto wrapper, solo quieres la lista validada. La solución a esto es validar tipos arbitrarios con TypeAdapter. En Pydantic, el workflow estándar gira en torno a definir una clase que hereda del base model. Ese model te da acceso a métodos muy potentes para parsear y serializar datos. Pero Pydantic es perfectamente capaz de validar tipos estándar de Python, como un diccionario normal, un integer suelto, una dataclass estándar o un typed dict. El problema es que estos tipos estándar no tienen de por sí los métodos de validación de Pydantic. No puedes llamar a validate en una lista estándar de Python. Aquí es donde entra en juego el type adapter. Actúa como un puente, envolviendo cualquier tipo arbitrario de Python y exponiendo todos los métodos familiares del model para ese tipo. Imagina un endpoint web que acepta un array JSON raw de strings. En el pasado, a lo mejor habrías creado un model dummy con un único campo llamado items, solo para poder pasarle el payload JSON. Esto obliga al cliente a enviar un objeto JSON con una key items, o te obliga a desempaquetar el model validado más tarde. Con un type adapter, te saltas el model dummy por completo. Primero, instancias el adapter y le pasas la definición de tipo exacta que esperas. En este caso, le pasas el type hint de Python para una lista de strings. Esto crea un objeto adapter configurado específicamente para esa estructura exacta. Ahora, tienes acceso a los métodos de validación estándar. Coges el payload JSON raw de tu endpoint y se lo pasas al método validate json en tu instancia del adapter. Pydantic parsea el byte string raw, comprueba que es un array JSON, verifica que cada elemento de dentro es un string, y devuelve una lista estándar de Python. Si el payload contiene un integer o un boolean, lanza un error de validación exactamente igual que haría un model normal. Aquí está la clave. El adapter no se limita a una simple validación. Refleja por completo la API core de un model estándar. Esto significa que también puedes usarlo para serializar datos. Si tienes un diccionario complejo o una dataclass estándar de Python y necesitas convertirlo de vuelta a un JSON string, le pasas esos datos al método dump json de tu adapter. Aplica exactamente las mismas reglas de serialización, custom encoders y formato que Pydantic aplica a los models normales. Esta funcionalidad es especialmente útil cuando trabajas con typed dicts. Un typed dict proporciona tipado estructural para los diccionarios estándar de Python, pero hace cero validación en runtime. Al pasarle un typed dict a un adapter, obtienes una validación completa de la estructura del diccionario en runtime. Asegura que todas las keys requeridas estén presentes y que los valores coincidan con los tipos esperados, sin convertir el diccionario en una instancia de objeto. El output sigue siendo un simple diccionario. Instanciar un adapter requiere que Pydantic construya esquemas de validación internos. Como este proceso de setup lleva un poco de tiempo de computación, deberías crear tus instancias del adapter a nivel de módulo en lugar de reconstruirlas dentro de una función cada vez que se llama a un endpoint. Define el adapter una sola vez al principio de tu archivo, y reutilízalo en múltiples requests. El type adapter te da todo el poder del motor de validación core para cualquier tipo estándar de Python, manteniendo tus estructuras de datos limpias y libres de clases wrapper innecesarias. Eso es todo por hoy. Gracias por escuchar, ve a crear algo genial.
8

Tipos Union y validación inteligente

4m 03s

Entiende las complejidades de la validación de tipos Union. Aprenderás cómo el Smart Mode de Pydantic evalúa la exactitud y los campos válidos para elegir la mejor coincidencia.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Data Validation, episodio 8 de 20. Cuando un campo está anotado como un Union de un string o un integer, y le pasas el integer 123, ¿qué validación intenta hacer Pydantic primero? Si asumes que simplemente lee tu código de izquierda a derecha, te podrías sorprender cuando tus datos se comporten de forma distinta a la esperada. Esto nos lleva a los Union Types y la Smart Validation. Un Union Type permite que un solo campo acepte varios tipos de datos distintos. Validar Unions es inherentemente complejo porque Pydantic intenta activamente hacer coerción de los datos al tipo solicitado. Un integer puede convertirse fácilmente en un string, y un string con dígitos puede parsearse a un integer. Si el motor de validación simplemente cogiera la primera coincidencia que encuentra, tu output cambiaría por completo basándose únicamente en el orden arbitrario en el que listaste los tipos en tu código. Este comportamiento rígido existe, y se llama modo Left to Right. En este modo, el sistema evalúa el input contra el primer tipo definido en el Union. Si la validación tiene éxito, se detiene inmediatamente. Si falla, pasa al segundo tipo. Si tu campo está tipado como string o integer, en ese orden, y le pasas el integer 123, el modo Left to Right evalúa primero la condición del string. Como el integer 123 puede ser coercionado sin problemas al string "123", la validación pasa. Tu integer se convierte silenciosamente en un string solo porque el string se escribió primero. Aquí está la clave. Por defecto, Pydantic evita esta trampa usando el Smart Mode. En lugar de detenerse en la primera coincidencia aceptable, el Smart Mode evalúa el input contra todos los tipos posibles en el Union. Luego compara las validaciones exitosas y elige la mejor coincidencia basándose en criterios de puntuación específicos. El criterio principal para los tipos simples es la exactitud. El Smart Mode penaliza fuertemente la coerción de datos. Volviendo a nuestro escenario anterior con un campo tipado como string o integer. Cuando pasas el integer 123, el Smart Mode prueba ambas opciones. Reconoce que el input puede ser coercionado a un string válido, pero también ve que el input ya es una coincidencia perfecta y exacta para un integer. Como una coincidencia exacta siempre obtiene mejor puntuación que una coincidencia coercionada, el Smart Mode devuelve correctamente el integer 123, independientemente de qué tipo se escribiera primero en el Union. Cuando tu Union contiene modelos de datos complejos en lugar de tipos básicos, el Smart Mode se basa en una métrica diferente. Cuenta el número de campos válidos que se han seteado. El motor evalúa el diccionario de input contra cada modelo en el Union. Calcula cuántos campos en el input mapean exactamente con los campos definidos de cada modelo. El modelo que absorbe con éxito el mayor número de campos del input sin lanzar errores de validación se declara el ganador. Esto evita que un modelo más pequeño y menos específico se trague datos que claramente estaban destinados a un modelo más grande y detallado en el mismo Union. La Smart Validation asegura que tus datos conserven su forma original precisa siempre que sea posible, protegiéndote de errores de coerción silenciosos que son notoriamente difíciles de rastrear en producción. ¡Gracias por escuchar, feliz coding a todos!
9

Herramienta avanzada: Discriminated Unions

3m 48s

Potencia el rendimiento de tu validación. Aprenderás a usar Discriminated (Tagged) Unions para decirle a Pydantic exactamente qué esquema aplicar basándose en un campo específico.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Validación de datos, episodio 9 de 20. Validar un payload entrante contra veinte modelos de datos diferentes mediante prueba y error es una pesadilla de rendimiento. Cuando tu sistema recibe un evento genérico, adivinar qué schema aplicar desperdicia ciclos de CPU y genera mensajes de error muy confusos cuando falla la validación. Puedes saltarte este juego de adivinanzas por completo usando una herramienta muy potente: las Discriminated Unions. Una union estándar le dice a Pydantic que un campo podría ser uno de varios modelos diferentes. Por defecto, Pydantic coge los datos entrantes y los prueba contra el primer modelo. Si falla, prueba con el segundo, y así sucesivamente. Este parsing secuencial es ineficiente. Las Discriminated Unions solucionan esto usando un tag explícito. Imagina que estás montando una pipeline de analítica que recibe diferentes tipos de eventos, como un evento de click, un evento de scroll y un evento de compra. Cada evento requiere diferentes campos de datos. El modelo de click podría necesitar un ID de elemento, mientras que el modelo de compra necesita el importe de la transacción. Para configurar una Discriminated Union, añades un campo compartido a cada uno de los modelos de ese grupo. Podrías llamar a este campo event type. Luego, le asignas un tipo literal string a este campo. El modelo de click fuerza que el event type sea exactamente el string click. El modelo de compra fuerza estrictamente el string purchase. A continuación, creas tu modelo de payload principal. Este modelo tiene un único campo event, definido como una union de tus modelos de eventos específicos. Aquí es donde configuras el discriminador. Envuelves la definición de la union en una configuración de campo de Pydantic, y asignas el string event type al argumento del discriminador. Aquí está la clave. Cuando llega un payload, Pydantic ya no prueba los modelos uno por uno. Mira directamente la key event type en los datos entrantes. Si el valor es purchase, Pydantic enruta inmediatamente todo el payload al modelo de compra. Es un lookup directo. Si falta el importe de la transacción, el mensaje de error indica claramente que falta un campo obligatorio para un evento de compra, en lugar de generar una parrafada enorme explicando cómo los datos fallaron al hacer match con todos los tipos de eventos posibles. Eso cubre una estructura limpia donde cada payload comparte una key de primer nivel. A veces te enfrentas a datos de terceros no estructurados donde el tag identificador está anidado dentro de otro objeto, o el modelo correcto depende de la presencia de keys específicas en lugar de un único valor dedicado. Para estas situaciones, Pydantic proporciona discriminadores callable. En lugar de pasarle el nombre de un campo string al argumento del discriminador, le pasas una función personalizada. Esta función recibe los datos de entrada raw y sin validar. Escribes la lógica dentro de esta función para inspeccionar el diccionario raw, encontrar cualquier pista que determine el tipo de datos, y devolver un string tag simple que represente el modelo correcto. Pydantic ejecuta tu función primero, recibe el string tag de vuelta, y lo usa para enrutar los datos al modelo preciso en la union. Usar una Discriminated Union transforma la validación de un juego de adivinanzas secuencial a un lookup preciso y de tiempo constante. ¡Gracias por escuchar, que tengáis todos un gran día!
10

Preprocesamiento con Before Validators y Wrap Validators

4m 19s

Maneja datos entrantes desordenados antes de que lleguen a tu esquema. Aprenderás a usar los validadores de campo Before y Wrap para limpiar la entrada en bruto antes de que Pydantic la evalúe.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Validación de datos, episodio 10 de 20. A veces, los datos entrantes son tan desordenados que el parsing estándar falla en cuanto tocan tu model. Tienes que interceptar y sanear el input en crudo antes de que el framework siquiera intente leerlo. Esto es exactamente lo que te permite hacer el preprocesamiento con los validadores Before y Wrap. Pydantic normalmente hace un trabajo excelente convirtiendo automáticamente los datos al tipo correcto. Pero si la forma fundamental de los datos está completamente mal, la conversión falla de inmediato. Un validador Before está diseñado para este problema. Es una función asociada a un campo que se ejecuta antes de que Pydantic haga cualquier comprobación de tipos o conversión propia. Recibe el input en crudo, intacto, exactamente como se le pasó al model. Imagina un escenario donde tu model define un campo que requiere estrictamente una lista de enteros. Sin embargo, estás consumiendo una API externa que envía incorrectamente estos datos como un único string continuo de números separados por comas, como el string uno coma dos coma tres. Pydantic espera un array, ve un solo string y lo rechaza con un error de validación. Esto lo arreglas escribiendo un validador Before. Dentro de tu función validadora, miras el input en crudo. Compruebas si el valor es un string. Si lo es, divides ese string por cada coma, lo que crea una lista de caracteres de string individuales. No tienes que convertir esos caracteres a enteros tú mismo. Simplemente devuelves la lista recién creada. Pydantic toma el relevo a partir de ahí. Ve la lista que esperaba, ejecuta su coerción interna estándar y convierte esos valores string en enteros por ti. Solo necesitabas arreglar la forma estructural de los datos. Eso cubre los inputs que se ejecutan antes de la lógica principal. El siguiente nivel de control es el validador Wrap. Los validadores Wrap son la herramienta de validación más flexible que ofrece Pydantic. En lugar de ejecutarse simplemente antes del paso de validación, un validador Wrap rodea literalmente el motor de validación interno de Pydantic para ese campo. Cuando escribes un validador Wrap, tu función recibe dos argumentos. El primero son los datos del input en crudo, igual que el validador Before. El segundo argumento es una función handler. Este handler representa la lógica central de validación y coerción de Pydantic. Aquí es donde la cosa se pone interesante. Tú decides exactamente cuándo, o incluso si, se ejecuta esa función handler. El flujo de la lógica está completamente en tus manos. Puedes inspeccionar el input en crudo y modificarlo. Luego, llamas explícitamente al handler, pasándole tus datos limpios. Pydantic ejecuta su comprobación de tipos interna sobre lo que le has proporcionado y devuelve el valor completamente parseado a tu validador. Luego puedes modificar ese valor parseado de nuevo antes de pasarlo al model final. Como tú controlas cuándo se ejecuta el handler, puedes meterlo dentro de un bloque try except estándar. Si la validación interna de Pydantic lanza un error, lo capturas ahí mismo en el validador Wrap. Puedes loguear el error, alterar los datos y probar de nuevo, o simplemente devolver un valor por defecto seguro. Incluso puedes escribir lógica que se salte el handler por completo para ciertos inputs específicos, omitiendo la validación estándar del todo. Los validadores Before sanean las formas incorrectas de los inputs para que Pydantic pueda leerlos, mientras que los validadores Wrap te dan autoridad total sobre todo el ciclo de vida de validación alrededor de un solo campo. Eso es todo por este episodio. ¡Gracias por escuchar y sigue programando!
11

Postprocesamiento con After Validators y Plain Validators

3m 33s

Aplica reglas estrictas de lógica de negocio. Aprenderás a usar After Validators para verificar datos ya parseados, y Plain Validators para cortocircuitar Pydantic por completo.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Data Validation, episodio 11 de 20. Comprobar si un string tiene formato de email es sencillo. Verificar que los datos cumplen con una lógica de negocio estricta, como cruzar datos con un sistema externo o aplicar reglas matemáticas específicas, requiere un lugar seguro para ejecutar código custom. Eso es exactamente lo que ofrece el post-processing con los validadores After y Plain. Cuando defines un campo en un modelo de Pydantic, la librería comprueba automáticamente el input contra el type hint. Los tipos solo te llevan hasta cierto punto. Un integer es un integer, ya sea uno o un millón. Para aplicar reglas más allá de los tipos básicos, añades funciones de validación custom. Pydantic te permite inyectar estas funciones en el lifecycle de validación. El punto de inyección más común es el validador After. Como su nombre indica, este se ejecuta después de que Pydantic termine su parsing interno y el type coercion. Aquí está la clave. Cuando tu función custom recibe los datos en un validador After, Pydantic garantiza que los datos ya coinciden con el tipo del campo. No tienes que escribir código boilerplate para gestionar la conversión de tipos o capturar tipos de datos inesperados. Imagina un escenario donde necesitas asegurarte de que un campo integer sea un número par. Defines un modelo con un campo tipado como integer. Luego, escribes una función custom que recibe un valor como argumento. Como configuras esta función como un validador After, sabes que el valor es absolutamente un integer. Simplemente usas el operador módulo para comprobar si al dividir el valor entre dos queda un resto. Si el resto no es cero, lanzas un ValueError estándar de Python con un mensaje personalizado. Si el resto es cero, devuelves el valor. Pydantic coge ese valor devuelto y lo asigna al modelo. La división del trabajo es limpia. Pydantic aplica el tipo, y tú aplicas la regla de negocio. A veces, el parsing por defecto de Pydantic se interpone en tu camino. Ahí es donde entra en juego el validador Plain. Un validador Plain reemplaza por completo la validación interna de Pydantic para un campo específico. Pydantic se hace a un lado y le pasa el input raw sin validar directamente a tu función custom. Usas un validador Plain cuando las reglas de coercion estándar no encajan con tu caso de uso, o cuando estás lidiando con una estructura de datos muy custom que Pydantic no entiende de forma nativa. En este escenario, tu función es responsable de todo. Recibe el input raw, realiza cualquier type checking necesario, convierte los datos y aplica la lógica de negocio. Si algo falla, tu función debe lanzar un ValueError o un AssertionError. Si tiene éxito, devuelve el valor final y limpio para el modelo. Puedes adjuntar ambos validadores a los campos usando decoradores de Pydantic en los métodos de clase, o añadiéndolos como metadatos directamente dentro del type hint usando anotaciones. La elección entre ellos se reduce a cuánto trabajo quieres hacer tú mismo. Usa un validador After cuando quieras que Pydantic haga el trabajo pesado de la conversión de tipos, y recurre a un validador Plain solo cuando necesites control absoluto sobre el parsing del input raw desde cero. Gracias por escuchar, nos vemos en la próxima.
12

Hooks de validación a nivel de modelo

3m 57s

Valida interacciones a través de múltiples campos. Aprenderás a usar el decorador model_validator para aplicar reglas que dependen de todo el payload.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Validación de datos, episodio 12 de 20. Validar campos de forma aislada funciona perfectamente, justo hasta el momento en que tu lógica de negocio dicta que el campo B solo se puede configurar si el campo A tiene un valor específico. Cuando la integridad de los datos depende de la interacción de varios campos, necesitas hooks de validación a nivel de modelo. En Pydantic, gestionas los campos interdependientes usando el decorador model validator. A diferencia de los field validators que se centran en un único dato de entrada, un model validator analiza toda la estructura de datos a la vez. Pydantic ofrece tres modos para este decorador: before, after y wrap. Estos determinan exactamente cuándo se ejecuta tu lógica personalizada durante el ciclo de vida de parsing. Vamos a aplicar esto a un modelo estándar de registro de usuarios. Tienes dos campos: password y password repeat. Una comprobación a nivel de campo puede verificar la longitud o la complejidad, pero no puede comparar los dos. Para eso, usas un model validator en modo after. El modo after se ejecuta una vez que Pydantic ha parseado y validado correctamente todos los campos individuales. En esta etapa, tu función de validación recibe el propio modelo instanciado. Simplemente escribes la lógica que comprueba si el atributo password del modelo es igual a su atributo password repeat. Si son diferentes, lanzas un ValueError. Aquí está la clave. Al usar el modo after, tu función debe devolver explícitamente la instancia del modelo, generalmente llamada self, al final del método. Si te olvidas de devolver self, Pydantic descartará tus datos validados y no devolverá nada. A veces necesitas interceptar los datos antes. Ahí es donde entra en juego el modo before. Un model validator en modo before se ejecuta antes de que Pydantic intente cualquier parsing o coerción de tipos. En lugar de una instancia de modelo tipada, tu función recibe el raw input, que normalmente es un diccionario. Usas este modo cuando la estructura de datos raw es un desastre y necesita ajustes antes de que la validación estándar pueda siquiera empezar. Por ejemplo, si las requests de una API legacy envían configuraciones de password en un diccionario anidado, un before validator puede extraer esos strings y aplanarlos en las keys de nivel superior que espera tu modelo de Pydantic. La función entonces devuelve el diccionario modificado, pasándolo por la chain. El tercer modo es wrap. Esto es para tener un control total sobre el ciclo de vida de validación. Un wrap validator recibe los datos del raw input y una función handler. Ejecutas tu lógica de preprocesamiento, llamas explícitamente al handler para disparar la validación interna de Pydantic, y luego ejecutas el postprocesamiento sobre el resultado. Usas esto cuando necesitas capturar errores de validación internos de Pydantic, loguearlos en un sistema externo, y quizás devolver un mensaje de error modificado o un objeto fallback por defecto. Elegir el modo adecuado es solo cuestión de timing. Usa before para dar forma al raw input, after para comparar campos fuertemente tipados, y wrap para controlar la propia ejecución de la validación. Si estos episodios te resultan útiles y quieres apoyar el programa, puedes buscar DevStoriesEU en Patreon. Eso es todo por este episodio. ¡Nos vemos en el próximo!
13

Serialización: Volcando datos de forma segura

4m 02s

Controla cómo salen tus datos del sistema. Aprenderás las diferencias entre volcar a dicts de Python frente a cadenas JSON, y cómo excluir campos no establecidos o por defecto.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Validación de datos, episodio 13 de 20. Introducir datos válidos en tu sistema es solo la mitad del trabajo. Cuando llega el momento de devolver esos datos a un frontend, a menudo te encuentras con payloads inflados con campos vacíos y valores por defecto que el usuario nunca llegó a proporcionar. La serialización, o hacer un dump de datos de forma segura, es la manera de limpiar ese flujo de salida. Una vez que tus datos están a salvo dentro de un modelo de Pydantic, tarde o temprano necesitas extraerlos para enviarlos a otro sitio. Tienes dos formas principales de hacerlo. La primera es llamar a model dump. Este método lee tu modelo y devuelve un diccionario de Python normal y corriente. La segunda es llamar a model dump json. Este método se salta el paso del diccionario y devuelve un string de JSON completamente formateado, listo para enviarse por la red. La diferencia entre estas dos opciones va un poco más allá de un simple diccionario frente a un string. Todo se reduce a los modos de serialización. Por defecto, model dump opera en modo Python. Si tu modelo contiene un tipo complejo, como un objeto datetime, el diccionario resultante seguirá conteniendo un objeto datetime de Python. Por otro lado, model dump json opera en modo JSON. JSON no sabe lo que es un objeto datetime de Python, así que Pydantic lo convierte automáticamente en una representación de string estándar. Aquí está la clave. De hecho, puedes forzar que la salida del diccionario utilice el modo JSON. Si llamas a model dump y pasas el argumento mode configurado como json, Pydantic devuelve un diccionario donde todos los tipos complejos ya se han traducido a formatos básicos compatibles con JSON, como strings y enteros. Eso soluciona lo de los tipos, pero aún tienes que gestionar la forma del payload. Imagina un modelo de perfil de usuario que devuelve datos a un frontend. El modelo podría definir veinte campos posibles. Un nuevo usuario se registra y solo proporciona su nombre y correo electrónico. Los otros dieciocho campos toman el valor de strings vacíos, nulls o URLs de avatar por defecto. Si le haces un dump a ese modelo normalmente, envías los veinte campos al frontend. Para solucionar esto, Pydantic proporciona tres keyword arguments específicos que puedes pasar a cualquiera de los métodos dump. El más preciso es exclude unset. Cuando pones exclude unset en true, Pydantic rastrea exactamente qué campos se rellenaron al crear el modelo. Solo incluirá en el dump el nombre y el correo electrónico. Los dieciocho campos por defecto se quedan completamente fuera del diccionario o del string de JSON. Esto asegura que nunca filtres datos de fallback que el usuario no llegó a enviar realmente. Si quieres un comportamiento ligeramente distinto, puedes usar exclude defaults. Este flag le dice a Pydantic que omita cualquier campo que coincida actualmente con su valor por defecto. Le da igual si el usuario envió explícitamente ese valor por defecto o si el sistema lo rellenó automáticamente. Si el valor coincide con el valor por defecto, se elimina del output. Finalmente, está exclude none. Si pones esto en true, Pydantic eliminará cualquier campo donde el valor sea actualmente none. Esto es puramente una comprobación de valor e ignora por completo el rastreo de defaults o unset. Estos flags de exclusión te dan un control estricto sobre tu tráfico de red y las respuestas de la API. Mantén tus modelos internos completamente exhaustivos, pero utiliza tus métodos dump para asegurarte de que tus payloads externos se mantengan exactamente tan ligeros como necesiten ser. Gracias por escuchar. ¡Hasta la próxima!
14

Personalizando la lógica de serialización

3m 27s

Cambia cómo se representan tus tipos a la salida. Aprenderás a escribir serializadores personalizados de Field y Model para mutar los datos durante la fase de volcado.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Validación de datos, episodio 14 de 20. ¿Qué pasa si almacenas una fecha internamente como un objeto datetime de Python, pero el contrato de la API de tu frontend requiere un timestamp de Unix como un integer raw? Podrías iterar sobre los datos justo antes de enviarlos, pero eso es un lío y es propenso a errores. La forma más limpia es personalizar la lógica de serialización directamente en tus modelos de Pydantic. Pydantic te da decoradores para interceptar el momento exacto en que un modelo se convierte de nuevo en un diccionario o JSON. Empezaremos con los field serializers. Un field serializer apunta a un atributo específico. Para crear uno, escribes un método normal dentro de la clase de tu modelo y pones el decorador field serializer justo encima. Le pasas al decorador el nombre del campo que quieres modificar. Veamos el ejemplo de datetime. Tienes un modelo con un atributo llamado created at, tipado como un datetime estándar de Python. Dentro del modelo, creas un método llamado serialize created at. El nombre del método no importa. Encima, pones el decorador field serializer, apuntando al campo created at. El método recibe el valor datetime como input. Dentro del método, llamas a la función timestamp estándar sobre ese datetime y devuelves el integer resultante. Ahora, cada vez que el modelo hace un dump de sus datos, Pydantic intercepta el campo created at, ejecuta tu método personalizado y devuelve un integer limpio en lugar de un string con formato ISO. Aquí está la clave. Los serializers operan en dos modos distintos: plain y wrap. El modo plain es el predeterminado. Cuando un serializer está en modo plain, Pydantic descarta por completo su propia lógica interna para ese campo y solo ejecuta tu código personalizado. Es un override completo. Pero a veces necesitas ejecutar primero la lógica predeterminada y luego modificar el resultado. O tal vez quieras capturar errores relacionados con el comportamiento predeterminado. Ahí es cuando usas el modo wrap. Para habilitarlo, le pasas mode igual a wrap al decorador. En el modo wrap, tu método recibe un segundo argumento llamado handler. Este handler es una referencia a la lógica de serialización interna de Pydantic. Puedes llamar al handler para obtener el output por defecto, inspeccionarlo, modificarlo o hacer un fallback a él si tu lógica personalizada falla. Esto cubre campos individuales. Si necesitas cambiar la estructura de todo el output, usas un model serializer. La configuración es casi idéntica, pero el decorador se coloca encima de un método que opera sobre toda la instancia del modelo. En lugar de recibir un único valor de campo, el método accede a los atributos del modelo en sí. Si pones un model serializer en modo plain, devuelves una estructura de diccionario completamente nueva desde cero. Si lo pones en modo wrap, tu método recibe un argumento handler, igual que el field serializer. Llamas al handler para obtener primero el diccionario estándar del modelo. Luego puedes añadir nuevas top-level keys, eliminar datos privados o aplanar estructuras anidadas antes de devolver el diccionario final. El aspecto más potente de estos decoradores es que desacoplan tus tipos internos de Python de tus contratos de API externos, manteniendo una validación estricta en la entrada y un formato preciso en la salida. Eso es todo por este episodio. Gracias por escuchar, ¡y seguid construyendo!
15

Generando JSON Schema a partir de modelos

4m 28s

Convierte tus modelos en contratos de API autodocumentados. Aprenderás a generar JSON Schemas compatibles con OpenAPI e inyectar ejemplos directamente en el esquema.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Validación de datos, episodio 15 de 20. Si tus schemas de API ya están estrictamente tipados en Python, tener que mantener un fichero YAML aparte para tu documentación OpenAPI es una enorme pérdida de tiempo. Acabas manteniendo dos fuentes de la verdad que inevitablemente se desincronizan. Generar el JSON Schema directamente desde tus modelos resuelve este problema de sincronización. Cada modelo de Pydantic incluye un método llamado model json schema. Al llamar a este método, Pydantic inspecciona tu modelo. Lee los campos, los tipos, los valores por defecto y las restricciones de validación. Luego, traduce toda esa lógica interna de Python a un diccionario de JSON Schema estándar. En concreto, Pydantic genera el Draft 2020-12 de la especificación JSON Schema. Esta es la parte importante. Dado que el output se ajusta a este estándar ampliamente aceptado, es compatible de forma nativa con OpenAPI. Defines tus reglas de validación estrictas una sola vez en Python, y el framework proporciona automáticamente la definición exacta del schema que tus consumidores externos necesitan. No hace falta ninguna traducción manual. La generación de schemas estándar maneja los tipos y las restricciones básicas a la perfección. Sin embargo, a veces necesitas comunicar lógica de negocio o formatos específicos que no se pueden inferir solo con un type hint de Python. Imagina un escenario en el que estás creando un modelo Configuration para un nuevo servicio. El modelo contiene un campo que acepta un diccionario de settings personalizados. El equipo de frontend necesita saber exactamente cómo es un payload válido, en lugar de solo saber que es un objeto genérico. Para resolver esto, utilizas una funcionalidad llamada json schema extra. Este parámetro te permite inyectar metadatos personalizados arbitrarios directamente en el JSON Schema generado. Puedes usarlo para añadir ejemplos mock, descripciones personalizadas o marcadores de palabras clave específicos que tu API gateway pueda requerir. Puedes aplicar json schema extra en dos niveles distintos. Puedes adjuntarlo a un campo individual o puedes aplicarlo a todo el modelo. Para proporcionar un ejemplo mock para ese campo settings específico, defines tu modelo Configuration. Para el atributo settings complejo, le asignas una función Field. Dentro de esa función Field, proporcionas el argumento json schema extra. Le pasas un diccionario que contiene la clave estándar de JSON Schema llamada examples. El valor asociado a esta clave es una lista que contiene tu payload de configuración mock exacto. Alternativamente, si quieres documentar el modelo completo en lugar de un solo campo, defines un diccionario model config en la clase. Dentro de ese diccionario de configuración, proporcionas json schema extra con un ejemplo a nivel de schema. Este enfoque es muy útil cuando quieres mostrar cómo interactúan varios campos juntos en un request body completo. Cuando ejecutas model json schema en tu modelo Configuration, Pydantic construye el árbol del schema estándar. Al llegar a tus campos o a la configuración del modelo, fusiona tu diccionario examples personalizado directamente en el output estándar. Las herramientas del frontend leen este schema, analizan la propiedad examples e inmediatamente muestran el payload mock a los desarrolladores. Saben exactamente qué enviar, y tu código Python sigue siendo la única fuente de la verdad. La verdadera potencia de la generación de schemas de Pydantic reside en que cualquier herramienta externa diseñada para el ecosistema JSON Schema puede consumir inmediatamente tus reglas de validación de Python sin necesidad de integración personalizada. Gracias por dedicarme unos minutos. Hasta la próxima. Que te vaya bien.
16

RootModel: Cuando tu payload no es un diccionario

3m 24s

Maneja payloads JSON no estándar con elegancia. Descubrirás cómo RootModel te permite parsear arrays y primitivas a nivel raíz mientras conservas los poderes de BaseModel.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Validación de datos, episodio 16 de 20. Los modelos estándar asumen que tu payload JSON entrante es un objeto mapeado con keys y values. Pero, ¿qué pasa cuando un endpoint necesita aceptar directamente un array top-level, o simplemente un string independiente, sin envolverlo en un diccionario? Precisamente para eso está diseñado RootModel: Cuando tu payload no es un diccionario. Cuando usas un modelo base estándar, Pydantic mapea los atributos de tu clase a las keys de JSON. Si le envías a un modelo estándar una lista raw, como un array JSON de números, la validación falla. Espera una estructura de diccionario. Para evitar esto, los desarrolladores suelen obligar al cliente a cambiar el payload. Crean una dummy key, tal vez llamada items, y envuelven el array en un objeto. Acabas doblando el diseño de tu API solo para tener contenta a tu librería de validación. RootModel elimina esa fricción. Es un modelo especial de Pydantic diseñado específicamente para payloads donde la estructura más externa es una lista, una tupla, o un tipo primitivo como un integer o un string. Imagina un endpoint de bulk-delete. Quieres que el cliente envíe un array JSON raw que contenga user IDs de tipo integer, y nada más. Para manejar esto, importas RootModel de Pydantic. Defines una nueva clase, tal vez llamada UserIdList, y haces que herede de RootModel. Parametrizas esa herencia con una lista de integers. Cuando el array JSON raw llega al servidor, lo pasas directamente al método model validate de tu clase UserIdList. Pydantic acepta el array top-level de forma nativa. Itera sobre el payload, se asegura de que cada elemento sea un integer válido, y devuelve una instancia del modelo completamente validada. Aquí está la clave. Aunque valida una lista plana, un RootModel proporciona exactamente la misma interfaz que un modelo normal. Sigues teniendo acceso a los métodos estándar. Puedes llamar a model dump para convertir los datos de nuevo a objetos Python, o a model dump json para generar un string raw. Como no hay campos con nombre en tu payload, necesitas una forma de acceder a los datos una vez validados. Pydantic almacena los datos parseados en un único atributo llamado exactamente root. Si quieres iterar sobre esos user IDs validados, simplemente iteras sobre el atributo root en la instancia de tu modelo. Este mecanismo no se limita a listas. Puedes definir un RootModel para un solo string o un integer. Si recibes un payload de string independiente, pero necesitas pasarlo por checks de longitud estrictos o pattern matching, definirlo como un RootModel de tipo string te permite adjuntar esas reglas de validación de forma nativa. Los datos siguen siendo un string simple en el payload, pero obtienen toda la protección del motor de validación. Siempre que te veas inventando una key de diccionario solo para que Pydantic tenga algo que parsear, estás usando la herramienta equivocada. Usa RootModel para adaptar tu capa de validación al contrato de tu API, en lugar de alterar el contrato de tu API para satisfacer a tu capa de validación. Gracias por escuchar. Cuidaos todos.
17

Dataclasses estándar vs Dataclasses de Pydantic

4m 22s

Lleva la validación a tus clases nativas de Python. Aprenderás cuándo usar el decorador dataclass de Pydantic para modernizar bases de código heredadas sin reescribir todo.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Data Validation, episodio 17 de 20. Tienes un codebase enorme construido completamente con dataclasses estándar de Python y te das cuenta de que necesitas urgentemente validación en runtime. Quizás pienses que tienes que reescribir todo para heredar de un BaseModel. No hace falta. Hoy, veremos las dataclasses estándar frente a las dataclasses de Pydantic. La librería estándar de Python incluye un decorador dataclass que es excelente para reducir el boilerplate. Te escribe los métodos de inicialización, representación e igualdad. Sin embargo, confía ciegamente en tus inputs. Si declaras un atributo age como un integer y le pasas un string, la dataclass estándar simplemente acepta el string. Proporciona type hints para el análisis estático, pero ofrece cero seguridad en runtime. Pydantic resuelve esto con su propio decorador dataclass. Está diseñado específicamente como un drop-in replacement para la versión de la librería estándar. Mantienes exactamente tu misma estructura de clases. No añades ninguna clase base. Simplemente cambias tu import para sacar el decorador del módulo pydantic dot dataclasses en lugar de la librería estándar. Imagina ese codebase legacy construido con dataclasses estándar. Encuentras una dataclass que maneja un objeto de configuración. Cambias el decorador estándar por el decorador de Pydantic. Al instante, cada vez que tu aplicación crea ese objeto de configuración, Pydantic intercepta la inicialización. Lee tus type hints existentes y los aplica. Si se le pasa un tipo no válido, Pydantic intenta hacer coerción. Si la coerción falla, lanza inmediatamente un ValidationError. Ganas asignaciones estrictas con type-checking, con cero cambios estructurales en tu árbol de herencia. Aquí está la clave. Si ambas opciones te dan validación, debes entender la diferencia entre una dataclass de Pydantic y un BaseModel estándar. Manejan los datos subyacentes de forma distinta. Un BaseModel está construido fundamentalmente en torno al parsing de diccionarios y proporciona una amplia gama de métodos built-in para exportar datos. Una dataclass de Pydantic sigue siendo una clase estándar de Python en su núcleo, manteniendo su memory footprint y comportamiento tradicionales. Como sigue siendo una clase estándar, la forma en que Pydantic aplica la validación cambia. Cuando instancias una dataclass de Pydantic, los argumentos se copian. Los datos pasan por el motor de validación core de Pydantic, que parsea y construye nuevos objetos para que coincidan con tus type hints. No se limita a referenciar los inputs mutables originales que le pasaste. Si le pasas una lista a una dataclass de Pydantic, el validador la procesa, valida los elementos internos y le asigna una lista completamente nueva a la instancia. La lista de input original y el atributo de tu dataclass ya no son el mismo objeto en memoria. Este comportamiento de copia asegura que tus datos se ajusten estrictamente al schema sin mutar las variables de input originales. La utilidad core de la dataclass de Pydantic es tender un puente entre los paradigmas estándar de Python y una validación rigurosa. Si necesitas una ruta de migración limpia para código legacy que ya usa dataclasses estándar, simplemente cambia el decorador para ganar type safety al instante, conservando toda la semántica de tu clase existente. Si te gusta el podcast y quieres apoyar el programa, puedes buscar DevStoriesEU en Patreon. Eso es todo por este episodio. ¡Gracias por escuchar, y sigue programando!
18

Ajuste fino de la configuración del modelo

3m 51s

Controla el rigor de todo tu modelo. Aprenderás a usar el ConfigDict para prohibir atributos adicionales, congelar instancias y validar asignaciones.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Validación de datos, episodio 18 de 20. Por defecto, Pydantic ignora silenciosamente cualquier key JSON extra que le envíes. En una API estricta, tragarse datos desconocidos sin previo aviso supone un grave riesgo de seguridad. Para solucionarlo, necesitas ajustar la configuración del modelo. Para cambiar cómo se comporta un modelo a nivel global, defines un atributo de clase llamado model config. Le asignas un ConfigDict, que es un diccionario tipado importado directamente de Pydantic. Pones esta asignación justo dentro de tu modelo, junto a las definiciones de tus campos. Como ConfigDict está tipado, tu editor de código detectará los errores tipográficos si intentas pasar una opción de configuración no válida. Las reglas que pongas en este diccionario determinarán cómo todo el modelo parsea, valida y almacena los datos. Vamos a crear un modelo de configuración de seguridad estricta para una aplicación. Un cliente malicioso podría enviar un payload JSON con campos inesperados, intentando, por ejemplo, inyectar un flag de admin o sobrescribir un parámetro oculto. Por defecto, Pydantic configura el comportamiento de los campos extra a ignore. Lee los campos que espera, descarta silenciosamente todos los datos desconocidos y crea el modelo. Para cerrar esta brecha, añades el parámetro extra a tu ConfigDict y estableces su valor al string forbid. Ahora, si un cliente envía una key inesperada, Pydantic lanza inmediatamente un error de validación. La request falla directamente, rechazando explícitamente el payload incorrecto antes incluso de que la lógica de tu aplicación lo procese. Esto gestiona la frontera entre el mundo exterior y tu sistema. Pero, ¿qué ocurre dentro de tu sistema después de crear el modelo? Normalmente, Pydantic solo valida los datos durante la inicialización. Si otro desarrollador escribe código que modifica un atributo en una instancia de modelo existente más adelante, Pydantic no interviene. Podrías asignar accidentalmente un raw string a un campo integer, y el modelo lo aceptaría. Para evitarlo, puedes poner validate assignment a true dentro de tu ConfigDict. Con esto activado, cada vez que se modifica un atributo en memoria, Pydantic intercepta el cambio y ejecuta exactamente la misma lógica de validación que utiliza durante la creación. A veces, incluso validar las mutaciones resulta demasiado permisivo para las configuraciones de seguridad. Quizás necesites una garantía absoluta de que la configuración no pueda modificarse en memoria por ninguna parte de tu código una vez que pase la comprobación inicial. Aquí es donde la cosa se pone interesante. Puedes poner el parámetro frozen a true en la configuración de tu modelo. Esto hace que toda la instancia del modelo sea inmutable. Si alguna función posterior intenta actualizar un campo, Pydantic lanza un error. Un modelo frozen se comporta exactamente como una tupla de Python. Como no puede cambiar, un modelo frozen es completamente seguro para compartir entre diferentes partes de tu aplicación, e incluso puede usarse de forma segura como key en un diccionario de Python o en una caché en memoria. Al apilar estas opciones de configuración dentro de tu ConfigDict, transformas un modelo de un parser de datos flexible a una frontera absoluta e inflexible. Eso es todo por este episodio. Gracias por escuchar, y sigue programando.
19

Configuración de aplicaciones con Pydantic Settings

4m 13s

Gestiona tus variables de entorno como un profesional. Aprenderás cómo el paquete pydantic-settings automatiza el parseo de secretos, archivos dot-env y prefijos.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Validación de datos, episodio 19 de 20. Deja de sacar strings del sistema operativo y cruzar los dedos para que casteen limpiamente a un integer. Probablemente hayas escrito docenas de archivos de utilidades haciendo wrap de llamadas estándar a variables de entorno solo para evitar que un valor de configuración faltante crashee tu aplicación en runtime. La configuración de aplicaciones con Pydantic Settings reemplaza todo ese boilerplate. Si bien Pydantic estándar se encarga de la validación general de datos, la gestión de variables de entorno requiere instalar el paquete independiente pydantic-settings. Este paquete proporciona una clase específica llamada BaseSettings. En lugar de obtener manualmente las variables y escribir lógica de parsing personalizada, declaras una clase que hereda de BaseSettings. Defines tus campos de configuración exactamente como un modelo Pydantic estándar, completo con type hints de Python y valores por defecto. Cuando instancias esta clase, Pydantic lee automáticamente las variables de entorno de tu sistema. Mapea los nombres de las variables a los atributos de tu clase, sin distinguir entre mayúsculas y minúsculas por defecto. Si definiste un campo de timeout de la base de datos como un integer, y la variable de entorno proporciona un string, Pydantic convierte ese string en un objeto integer real. Si la variable de entorno contiene texto arbitrario en lugar de un número, Pydantic lanza un error de validación claro inmediatamente en el startup de la aplicación. Tu programa falla rápido, en lugar de crashear de forma impredecible más adelante durante una call activa a la base de datos. En entornos más grandes, los nombres de las variables globales suelen colisionar. Es posible que tengas múltiples servicios corriendo en el mismo host, todos buscando una variable llamada simplemente database URL. BaseSettings resuelve esto permitiéndote definir un prefijo de entorno en la configuración del modelo. Si estableces el prefijo como app guion bajo, Pydantic deja de buscar coincidencias exactas en los nombres de los campos. En su lugar, para poblar un campo llamado database URL, apunta específicamente a la variable de entorno app guion bajo database URL. El código de tu aplicación Python sigue accediendo a la propiedad simplemente como database URL, ocultando por completo el prefijo del sistema operativo de tu lógica de negocio. Aquí está la clave. No tienes que aplanar tus objetos Python solo para leer variables de entorno. La configuración suele volverse compleja, requiriendo estructuras de datos anidadas. Es posible que tengas una clase principal de settings que incluya un submodelo dedicado para los settings de la base de datos, y otro para el logging. Pydantic permite resolver estas estructuras anidadas usando una convención de doble guion bajo. Si tu clase principal de settings tiene un campo llamado database, que a su vez apunta a un modelo que contiene un campo timeout, Pydantic buscará una variable de entorno llamada database doble guion bajo timeout. Si estás usando un prefijo, naturalmente también lo añade al principio, dando como resultado algo como app guion bajo database doble guion bajo timeout. Este mecanismo te permite mantener objetos de configuración jerárquicos y estrictamente tipados en tu código fuente, a la vez que se mapean limpiamente a variables de entorno estándar y planas. El verdadero valor de BaseSettings no es solo eliminar el código boilerplate, es garantizar que, si tu aplicación arranca correctamente, todo su estado de configuración está completamente presente, explícitamente tipado y es totalmente seguro de consumir. Gracias por escuchar, ¡happy coding a todos!
20

Bajo el capó: Core Schemas personalizados

4m 31s

¡Este es el episodio final de la serie! Toma el control absoluto del motor de validación. Aprenderás a escribir un método __get_pydantic_core_schema__ para enseñar al core en Rust cómo manejar objetos de Python completamente ajenos.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Pydantic: Validación de datos, episodio 20 de 20. Importas una library rígida y sin documentación de otro equipo, y necesitas pasar sus objetos por tu estricto pipeline de validación. El objeto no tiene ni idea de qué es Pydantic, y no puedes tocar su código fuente. Cuando las anotaciones y los validadores simples no son suficientes, tienes que hablar directamente con el motor, y eso significa abrir el capó para escribir core schemas personalizados. Normalmente, Pydantic averigua cómo validar tus datos leyendo los type hints. Cuando le pasas un objeto extraño, se choca contra un muro. Para solucionarlo, defines un método llamado dunder get pydantic core schema. Este método actúa como una capa de traducción directa. Se salta los wrappers de alto nivel de Python y le pasa las instrucciones directamente a Pydantic Core, el motor subyacente en Rust que maneja la lógica real de validación. Cuando implementas este método, recibe el tipo de origen y un handler. El handler funciona exactamente igual que un middleware en un framework web. No tienes que escribir todo el esquema de validación desde cero. Puedes pedirle al handler que genere el esquema por defecto para un tipo específico, y luego envolver ese resultado con tu propia lógica personalizada. Toma como ejemplo el wrapper de conexión a una base de datos legacy. Imagina que la única forma de inicializar este objeto es pasándole un entero específico, como un ID de conexión. Quieres que Pydantic acepte un entero de una petición a la API, lo valide y te devuelva el objeto de conexión completamente instanciado. Como no puedes modificar la clase legacy directamente, defines un tipo personalizado usando anotaciones de Python. Dentro de esa anotación, proporcionas tu método de core schema personalizado. Aquí está la clave. En lugar de escribir diccionarios a pelo, usas el módulo core schema de Pydantic, que proporciona funciones helper para construir estas estructuras de forma segura. Primero, le pides al handler que construya un esquema de entero estándar. Después, construyes un chain schema. Le indicas al motor que ejecute primero la validación de entero estándar. Si el input es realmente un entero, el motor se lo pasa a una función de Python personalizada que tú proporcionas. Esta función toma el ID de conexión, inicializa el wrapper de la base de datos legacy y devuelve el objeto. Finalmente, añades un esquema de comprobación de instancia al chain, asegurando que el output final sea exactamente la clase legacy que esperas. Aquí es donde la cosa se pone interesante. Devuelves esta estructura anidada a Pydantic. Bajo el capó, Pydantic coge estas definiciones de diccionarios anidados y las compila en un grafo de ejecución nativo en Rust. Has programado el motor de Rust desde Python, diciéndole paso a paso cómo ingerir un entero en bruto, validarlo y construir de forma segura un objeto extraño a la máxima velocidad. Esto representa el nivel más bajo de integración que ofrece Pydantic, dándote control total sobre el árbol de validación sin sacrificar el rendimiento. Como este es nuestro último episodio, te animo muchísimo a que te sumerjas en la documentación oficial de Pydantic e intentes construir un core schema personalizado de forma práctica. Es la mejor manera de consolidar cómo piensa realmente el motor. También puedes visitar dev stories dot eu para sugerir temas que te gustaría que cubriéramos en futuras series. Eso es todo por hoy. Gracias por escuchar... ¡ve a construir algo genial!