Capítulo 3.4: Operações CRUD para Naves Espaciais
Tempo de estudo: 1 hora
1. CRUD: Ciclo Completo de Gerenciamento de Missões Espaciais
Até agora, apenas lemos dados (Read
). Mas um verdadeiro Centro de Controle de Missões deve ser capaz de tudo:
- Create (Criar): Lançar um novo satélite em órbita.
- Read (Ler): Solicitar o status de uma nave existente.
- Update (Atualizar): Corrigir uma órbita ou atualizar software.
- Delete (Excluir): Remover um satélite antigo da órbita.
Essas quatro operações — CRUD — formam a base da maioria das APIs. Neste capítulo, implementaremos o ciclo completo para gerenciar nossa frota.
2. Create: Lançando uma Nova Nave (POST)
Para criar uma nova nave espacial, usaremos o método POST
. Os dados para a nova nave serão transmitidos no corpo da requisição em formato JSON.
Passo 1: Criando um novo modelo Pydantic para dados de entrada
Por que é necessário um novo modelo? Porque ao criar uma nave, não sabemos seu id
— ele deve ser atribuído pelo servidor.
Adicione este modelo ao main.py
:
# main.py
from pydantic import BaseModel, Field
class SpaceshipCreate(BaseModel):
"""Modelo para criar uma nova nave (sem ID)."""
name: str = Field(..., min_length=3, max_length=50)
type: str
launch_year: int = Field(..., gt=1950)
status: str
Spaceship
, mas será usado para validação de dados de entrada.
Passo 2: Implementando o endpoint POST /spaceships
# main.py
import random # Adicione esta importação no início do arquivo
# ... restante do código ...
@app.post("/spaceships", response_model=Spaceship, status_code=201)
def create_spaceship(ship: SpaceshipCreate):
"""
Adiciona uma nova nave espacial ao registro.
"""
# Geramos um novo ID exclusivo para a nave
new_id = max(db_spaceships.keys() or [0]) + 1
# Criamos um objeto de nave, correspondente ao modelo completo Spaceship
new_ship = Spaceship(id=new_id, **ship.dict())
# Salvamos em nossa "base de dados"
db_spaceships[new_id] = new_ship.dict()
return new_ship
@app.post(...)
: Usamos o decorador para requisiçõesPOST
.status_code=201
: Indicamos que, em caso de criação bem-sucedida, deve-se retornar o status201 Created
.ship: SpaceshipCreate
: Aí está a mágica! O FastAPI pegará automaticamente o corpo da requisição (JSON), o validará de acordo com o modeloSpaceshipCreate
e o passará para a função como um objetoship
.new_id = ...
: Lógica simples para gerar um novo ID.**ship.dict()
: "Desempacotamos" os dados do modeloship
recebido para o nosso modelo completo.response_model=Spaceship
: A resposta corresponderá ao modelo completo, incluindo oid
.
3. Update: Correção de Rota (PUT)
Para uma atualização completa de um recurso existente, o método PUT
é usado.
Implementando o endpoint PUT /spaceships/{ship_id}
:
# main.py
from fastapi import FastAPI, HTTPException # Atualize a importação
# ... restante do código ...
@app.put("/spaceships/{ship_id}", response_model=Spaceship)
def update_spaceship(ship_id: int, ship_update: SpaceshipCreate):
"""
Atualiza completamente os dados de uma nave espacial.
"""
if ship_id not in db_spaceships:
raise HTTPException(status_code=404, detail="Nave espacial não encontrada")
updated_ship = Spaceship(id=ship_id, **ship_update.dict())
db_spaceships[ship_id] = updated_ship.dict()
return updated_ship
ship_update: SpaceshipCreate
: Usamos novamente nosso modelo para validação dos dados de entrada.HTTPException
: Se uma nave com talid
não for encontrada, "lançamos" uma exceção padrão do FastAPI, que se transformará em uma bela resposta JSON com o código404
.
4. Delete: Desorbitando (DELETE)
Para excluir um recurso, o método DELETE
é usado. Geralmente, tal endpoint não retorna um corpo de resposta.
Implementando o endpoint DELETE /spaceships/{ship_id}
:
# main.py
from fastapi import FastAPI, HTTPException, Response, status # Atualize a importação
# ... restante do código ...
@app.delete("/spaceships/{ship_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_spaceship(ship_id: int):
"""
Exclui uma nave espacial do registro.
"""
if ship_id not in db_spaceships:
raise HTTPException(status_code=404, detail="Nave espacial não encontrada")
del db_spaceships[ship_id]
# Retorna uma resposta vazia com status 204
return Response(status_code=status.HTTP_204_NO_CONTENT)
status_code=status.HTTP_204_NO_CONTENT
: Nós explicitamente indicamos o status204 No Content
.del db_spaceships[ship_id]
: Excluímos o registro do nosso dicionário.return Response(...)
: Retornamos uma resposta vazia, pois o cliente não precisa de dados sobre o objeto excluído.
5. Testando o Ciclo Completo em /docs
Seu uvicorn
deve ter sido reiniciado.
- Abra
http://127.0.0.1:8000/docs
. Agora você tem o conjunto completo de operações CRUD! - POST: Expanda o endpoint
POST /spaceships
, clique em "Try it out", preencha o corpo JSON (por exemplo, crie o "Telescópio Espacial James Webb") e clique em "Execute". Você deve receber uma resposta201
com os dados do novo telescópio. - GET: Agora execute
GET /spaceships
. Seu novo telescópio deve aparecer na lista. - PUT: Use o ID do novo telescópio para atualizar seus dados via
PUT /spaceships/{ship_id}
. Por exemplo, altere seu status. - DELETE: Use o mesmo ID para excluir o telescópio via
DELETE /spaceships/{ship_id}
. Você deve receber uma resposta vazia com status204
. - Verificação: Execute
GET /spaceships
novamente para confirmar que o telescópio foi excluído da lista.
Questionário para Consolidação
🚀 Resumo do Capítulo:
Você implementou o ciclo completo de CRUD e transformou sua API de um simples "painel de informações" em um completo Centro de Controle de Frota!
- ✅ Create:
POST /spaceships
para lançar novas naves. - ✅ Read:
GET /spaceships
eGET /spaceships/{id}
para obter dados. - ✅ Update:
PUT /spaceships/{id}
para atualizar missões. - ✅ Delete:
DELETE /spaceships/{id}
para desativar naves.
Sua frota está sob controle total! No próximo capítulo, veremos como o FastAPI gerou automaticamente para nós um "manual de operações" detalhado – a documentação interativa do Swagger.
📌 Verificação:
- Todos os 5 endpoints (
GET
(2),POST
,PUT
,DELETE
) estão visíveis e funcionando em/docs
.- Você pode criar, ler, atualizar e excluir um recurso com sucesso.
- Ao solicitar um ID inexistente, um erro
404
é retornado.⚠️ Se houver erros:
NameError
: Verifique se você importouHTTPException
,Response
,status
.KeyError
: Provavelmente, você está tentando acessar um ID que já foi excluído.- Funcionamento incorreto de
PUT
ouPOST
: Certifique-se de estar usando o modelo Pydantic correto no argumento da função (SpaceshipCreate
).