Skip to content

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
Este modelo é quase idêntico a 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
Decifrando:

  • @app.post(...): Usamos o decorador para requisições POST.
  • status_code=201: Indicamos que, em caso de criação bem-sucedida, deve-se retornar o status 201 Created.
  • ship: SpaceshipCreate: Aí está a mágica! O FastAPI pegará automaticamente o corpo da requisição (JSON), o validará de acordo com o modelo SpaceshipCreate e o passará para a função como um objeto ship.
  • new_id = ...: Lógica simples para gerar um novo ID.
  • **ship.dict(): "Desempacotamos" os dados do modelo ship recebido para o nosso modelo completo.
  • response_model=Spaceship: A resposta corresponderá ao modelo completo, incluindo o id.

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 tal id não for encontrada, "lançamos" uma exceção padrão do FastAPI, que se transformará em uma bela resposta JSON com o código 404.

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 status 204 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.

  1. Abra http://127.0.0.1:8000/docs. Agora você tem o conjunto completo de operações CRUD!
  2. 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 resposta 201 com os dados do novo telescópio.
  3. GET: Agora execute GET /spaceships. Seu novo telescópio deve aparecer na lista.
  4. PUT: Use o ID do novo telescópio para atualizar seus dados via PUT /spaceships/{ship_id}. Por exemplo, altere seu status.
  5. DELETE: Use o mesmo ID para excluir o telescópio via DELETE /spaceships/{ship_id}. Você deve receber uma resposta vazia com status 204.
  6. Verificação: Execute GET /spaceships novamente para confirmar que o telescópio foi excluído da lista.

Questionário para Consolidação

1. Qual método HTTP é usado para criar um novo recurso?

2. O código de status de sucesso padrão para a operação `DELETE` é:

3. Como o FastAPI obtém dados do corpo de uma requisição POST?

4. `raise HTTPException(status_code=404)` é usado para:

5. Por que criamos um modelo `SpaceshipCreate` separado para a criação de um recurso (`POST`)?


🚀 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 e GET /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ê importou HTTPException, Response, status.
  • KeyError: Provavelmente, você está tentando acessar um ID que já foi excluído.
  • Funcionamento incorreto de PUT ou POST: Certifique-se de estar usando o modelo Pydantic correto no argumento da função (SpaceshipCreate).