Especialização em Backend com Python & FastAPI • Demonstrações Práticas Compiláveis


💻 Exemplo 1 — Constraints com Field e Validador de Campo Único

from pydantic import BaseModel, Field, field_validator

class ProdutoSchema(BaseModel):
    id: int = Field(..., gt=0)
    nome: str = Field(..., min_length=3, max_length=100)
    preco: float = Field(..., gt=0.0)
    tags: list[str] = Field(default_factory=list)

    @field_validator("tags")
    @classmethod
    def validar_tags_unicas(cls, v: list[str]) -> list[str]:
        if len(v) != len(set(v)):
            raise ValueError("Tags não podem ser duplicadas")
        return v

produto = ProdutoSchema(id=1, nome="Teclado Mecânico", preco=350.0, tags=["hardware", "usb"])
print(produto.model_dump())
# {'id': 1, 'nome': 'Teclado Mecânico', 'preco': 350.0, 'tags': ['hardware', 'usb']}

💻 Exemplo 2 — Validação Cruzada com model_validator e Serialização Customizada

from datetime import date

from pydantic import BaseModel, field_serializer, model_validator

class EventoSchema(BaseModel):
    nome: str
    data_inicio: date
    data_fim: date

    @model_validator(mode="after")
    def validar_intervalo_datas(self) -> "EventoSchema":
        if self.data_fim < self.data_inicio:
            raise ValueError("data_fim deve ser posterior a data_inicio")
        return self

class ClienteResponse(BaseModel):
    nome: str
    email: str
    saldo: float

    @field_serializer("email")
    def mascarar_email(self, email: str) -> str:
        usuario, dominio = email.split("@")
        return f"{usuario[0]}***{usuario[-1]}@{dominio}"

    @field_serializer("saldo")
    def formatar_saldo(self, saldo: float) -> str:
        return f"R$ {saldo:,.2f}".replace(",", "X").replace(".", ",").replace("X", ".")

evento = EventoSchema(nome="Conferência Tech", data_inicio=date(2026, 9, 1), data_fim=date(2026, 9, 3))
print("Evento válido:", evento.nome)

cliente = ClienteResponse(nome="Alice", email="alice@tech.com", saldo=1250.0)
print(cliente.model_dump())
# {'nome': 'Alice', 'email': 'a***e@tech.com', 'saldo': 'R$ 1.250,00'}

💻 Exemplo 3 — Modelos Imutáveis e Estritos com ConfigDict

from pydantic import BaseModel, ConfigDict, ValidationError

class TokenPayload(BaseModel):
    model_config = ConfigDict(frozen=True, extra="forbid", str_strip_whitespace=True)

    sub: str
    role: str
    exp: int

token = TokenPayload(sub="  user_42  ", role="ADMIN", exp=1780000000)
print(token.sub)  # "user_42" (espaços removidos por str_strip_whitespace)

try:
    token.role = "USER"  # frozen=True bloqueia reatribuição
except ValidationError as erro:
    print("Bloqueado:", erro.errors()[0]["type"])

try:
    TokenPayload(sub="user_1", role="ADMIN", exp=123, campo_extra="hack")
except ValidationError as erro:
    print("Rejeitado por extra='forbid':", erro.errors()[0]["type"])