Capítulo 3.3: Modelos de Dados com Pydantic
Tempo de estudo: 50 minutos
1. Pydantic: A "Planta Digital" da nave espacial
Imagine que você está construindo uma nave espacial. Você não pode simplesmente soldar pedaços de metal aleatoriamente. Você precisa de uma planta detalhada que defina:
- Nome da nave (tipo:
string
, comprimento máx.: 50 caracteres) - Ano de lançamento (tipo:
número inteiro
) - Presença de hipermotor (tipo:
sim/não
)
Pydantic é uma biblioteca que permite criar essas "plantas digitais" para seus dados em Python. No FastAPI, ela desempenha três funções chave:
- Declaração da estrutura: Descreve claramente quais campos seus dados contêm.
- Validação de dados: Verifica automaticamente se os dados de entrada correspondem à planta.
- Documentação: O FastAPI usa essas plantas para gerar documentação detalhada e interativa.
💡 Analogia espacial: Um modelo Pydantic é a ficha técnica de um objeto. Qualquer "carga" (dados) que chega à estação deve corresponder à especificação na ficha técnica. Caso contrário, o computador de bordo (Pydantic) a rejeitará.
2. Criando a primeira planta: Modelo Spaceship
Vamos criar um modelo que descreverá nossa nave espacial.
Passo 1: Importamos BaseModel
do Pydantic
Pydantic já está instalado junto com fastapi[all]
. Precisamos apenas importar a classe base para nossos modelos.
Adicione no main.py
no topo, ao lado de outras importações:
Passo 2: Descrevemos o modelo Spaceship
Crie uma classe que herda de BaseModel
. Dentro da classe, defina os campos e seus tipos, usando as anotações de tipo padrão do Python.
Adicione este código em main.py
(pode ser depois das importações):
class Spaceship(BaseModel):
"""
Ficha técnica (modelo) da nave espacial.
"""
name: str
type: str
launch_year: int
status: str
Spaceship
deve ter quatro campos com os tipos especificados.
3. Aplicando o modelo: Melhoramos nossos endpoints
Agora, vamos usar nosso novo modelo para tornar a API "mais inteligente".
A. Modelo como resposta (Response Model)
Podemos informar ao FastAPI que nosso endpoint deve retornar dados que correspondam ao modelo Spaceship
. Isso garante que a resposta sempre terá a estrutura correta.
Modifique o endpoint /spaceships/{ship_id}
da seguinte forma:
# main.py
# ... código com db_spaceships e o modelo Spaceship ...
# Usamos `response_model` para especificar a "planta" da resposta
@app.get("/spaceships/{ship_id}", response_model=Spaceship)
def get_spaceship(ship_id: int):
"""
Retorna os dados da nave, correspondentes ao modelo Spaceship.
"""
ship = db_spaceships.get(ship_id)
return ship
response_model=Spaceship
: Dizemos ao FastAPI: "A resposta desta função deve corresponder à estrutura Spaceship
. Filtre todos os campos extras e certifique-se de que os tipos estão corretos".
O que isso oferece?
- Filtragem de dados: Se
db_spaceships
tivesse campos extras (por exemplo,"secret_code"
), eles não seriam incluídos no JSON final. - Garantia de estrutura: O cliente da API pode ter certeza de que sempre receberá uma resposta no formato esperado.
- Documentação: Em
/docs
agora será exibido um exemplo exato da resposta (Example Value).
B. Modelos para coleções
E quanto ao endpoint /spaceships
, que retorna uma lista de naves? Para isso, precisamos usar list
do módulo typing
.
Modifique as importações e o endpoint /spaceships
:
# main.py no topo
from fastapi import FastAPI
from pydantic import BaseModel
from typing import List # <-- Importamos List
# ... código ...
# Indicamos que a resposta é uma lista (List) de objetos do tipo Spaceship
@app.get("/spaceships", response_model=List[Spaceship])
def get_spaceships():
"""
Retorna uma lista de naves. Cada item da lista
é verificado de acordo com o modelo Spaceship.
"""
# Pydantic não pode trabalhar com um dicionário cujas chaves são IDs.
# Convertemos nosso dicionário em uma lista simples.
return list(db_spaceships.values())
response_model=List[Spaceship]
: Indicamos que a resposta será uma lista, onde cada elemento é um objeto que corresponde ao modeloSpaceship
.return list(db_spaceships.values())
: Uma mudança importante! Pydantic espera um objeto iterável (uma lista), e não um dicionário onde as chaves são IDs. Convertemos os valores do nosso "simulador de BD" em uma lista.
4. Verificando a API aprimorada
Certifique-se de que o servidor uvicorn
esteja em execução com --reload
.
- Verifique
http://127.0.0.1:8000/spaceships
: Agora a resposta é um array JSON, e não um objeto. Esta é uma estrutura mais correta e padrão para coleções. - Verifique
http://127.0.0.1:8000/spaceships/1
: A resposta não mudou, mas agora está garantida para corresponder ao modelo. - Dê uma olhada em
/docs
: Na seção "Schemas" na parte inferior da página, seu modeloSpaceship
apareceu. E nos exemplos de resposta para os endpoints, agora é exibido um esquema de dados bonito e estruturado.
5. Validação avançada: O "computador de bordo" em ação
Pydantic pode fazer muito mais do que apenas verificar tipos.
Vamos adicionar validação ao nosso modelo Spaceship
:
from pydantic import BaseModel, Field
class Spaceship(BaseModel):
name: str = Field(..., min_length=3, max_length=50, description="Nome da nave")
type: str
launch_year: int = Field(..., gt=1950, description="O ano de lançamento deve ser depois de 1950")
status: str
Field(...)
: Usado para adicionar regras de validação adicionais....
(Ellipsis): Significa que o campo é obrigatório.min_length
,max_length
: Restrições para strings.gt
: "Greater Than" (maior que).
Embora ainda não estejamos criando novas naves (isso será na próxima seção), essas regras já serão refletidas na documentação e entrarão em vigor quando implementarmos as solicitações POST
.
Quiz para fixação
🚀 Resumo do Capítulo:
Você projetou os "projetos digitais" para os dados da sua API. Agora ela não apenas funciona, mas funciona de forma previsível e confiável.
- 📝 Modelo
Spaceship
criado usando Pydantic. - 🛡️ A API agora valida e filtra os dados de saída usando
response_model
. - 📊 A documentação tornou-se muito mais informativa, mostrando esquemas de dados precisos.
Os projetos estão prontos e aprovados! No próximo capítulo, passaremos da leitura de dados para a criação — implementaremos operações CRUD completas para a nossa frota.
📌 Verificação:
- Certifique-se de que o esquema do modelo
Spaceship
apareceu em/docs
.- Verifique se o endpoint
/spaceships
agora retorna um array JSON ([...]
), e não um objeto ({...}
).- Certifique-se de que não há erros de sintaxe no código após adicionar os modelos.
⚠️ Se houver erros:
NameError: name 'BaseModel' is not defined
: Verifique se você importouBaseModel
depydantic
.NameError: name 'List' is not defined
: Verifique se você importouList
detyping
.- A resposta para
/spaceships
está vazia ([]
): Certifique-se de que você alteroureturn db_spaceships
parareturn list(db_spaceships.values())
.