Pydantic já converte e valida tipos declarados; validadores personalizados devem tratar regras que o schema não expressa sozinho. field_validator atua em campos, enquanto model_validator verifica o objeto como conjunto.
from datetime import date
from typing import Self
from pydantic import BaseModel, field_validator, model_validator
class Periodo(BaseModel):
inicio: date
fim: date
@field_validator("inicio", "fim", mode="before")
@classmethod
def limpar_data(cls, valor: object) -> object:
return valor.strip() if isinstance(valor, str) else valor
@model_validator(mode="after")
def validar_ordem(self) -> Self:
if self.fim < self.inicio:
raise ValueError("fim deve ser posterior ao início")
return self
O modo before recebe a entrada bruta e deve lidar com qualquer objeto. O validador de modelo no modo after recebe a instância já validada e retorna self. Uma ordem de datas é regra entre campos, portanto pertence ao modelo.
Boas práticas
Mantenha validadores determinísticos e sem chamadas de rede ou banco. Levante ValueError com mensagem útil, sem expor segredos. Evite mutar a entrada antes de lançar erro em unions, pois outro ramo pode receber o objeto alterado. Cubra entradas válidas, limites e falhas em testes.
Comece pelo guia de Pydantic e separe configuração com Pydantic Settings.
A documentação oficial de validadores do Pydantic, consultada em 22 de julho de 2026, detalha a API e seus limites.