Este repositório contém a resolução do desafio prático "Desenvolvendo sua Primeira API com FastAPI, Python e Docker" da plataforma DIO (Digital Innovation One). O projeto consiste na criação de uma API RESTful completa para uma academia, permitindo o registo e a consulta de atletas, categorias e centros de treinamento.
O objetivo principal foi aplicar os conceitos aprendidos durante o curso, construindo uma aplicação robusta, desde a configuração do ambiente até à implementação dos endpoints, passando pela interação com a base de dados e a gestão de migrações.
A construção deste projeto foi um processo de aprendizagem intenso e realista, que envolveu a superação de diversos desafios de configuração e depuração. Esta seção documenta os principais obstáculos encontrados e as soluções aplicadas, refletindo o trabalho real de um desenvolvedor de software.
- Desafio: A configuração inicial do ambiente em Windows apresentou vários desafios, desde a instalação de ferramentas como pyenv e make, que não são nativas do sistema, até conflitos com a versão do Python instalada através da Microsoft Store.
- Solução Implementada:
- Python: Foi realizada uma instalação limpa do Python diretamente do site oficial (python.org), eliminando os conflitos causados pela versão da Microsoft Store.
- Ferramentas: O make foi instalado utilizando o gerenciador de pacotes nativo do Windows, winget, com o comando winget install GnuWin32.Make.
- Makefile: Os comandos no Makefile foram ajustados para serem compatíveis com o PowerShell do Windows, removendo a sintaxe PYTHONPATH=. (específica de Linux/macOS) e garantindo que a indentação usasse o caractere TAB em vez de espaços.
- Desafio: O Alembic inicialmente não conseguia encontrar os módulos da aplicação (ex: workout_api), resultando num ModuleNotFoundError. Posteriormente, ocorreram erros de NoReferencedTableError ao tentar criar as relações entre as tabelas.
- Solução Implementada:
- Foi adicionado um código ao topo do ficheiro alembic/env.py para incluir o diretório raiz do projeto no sys.path, permitindo que o Alembic "enxergasse" todos os pacotes.
- O erro de referência de tabela foi resolvido garantindo que todos os modelos do SQLAlchemy fossem importados no env.py antes de o target_metadata ser definido. Isto assegurou que o Alembic conhecia todas as tabelas antes de tentar criar as chaves estrangeiras.
- Desafio: O endpoint POST /atletas/ retornava um erro genérico 500 Internal Server Error, escondido por um bloco try...except Exception. Testes com o Postman provaram que o backend estava funcional, apontando para um problema subtil de serialização ou lógica.
- Solução Implementada:
- A lógica dentro da função post no atleta/controller.py foi refatorada. Em vez de criar um schema de saída (AtletaOut) e depois um modelo da base de dados, a abordagem foi simplificada:
- O AtletaModel é criado diretamente com os dados de entrada (AtletaIn).
- Os objetos de relacionamento (categoria e centro_treinamento) são associados diretamente ao modelo.
- Após o commit, o próprio atleta_model é retornado. O FastAPI encarrega-se da conversão para o AtletaOut (graças à configuração from_attributes=True no BaseSchema), tornando o código mais limpo e robusto.
- A lógica dentro da função post no atleta/controller.py foi refatorada. Em vez de criar um schema de saída (AtletaOut) e depois um modelo da base de dados, a abordagem foi simplificada:
- Desafio: Ao tentar criar um atleta com dados que violavam uma restrição unique (como um CPF ou nome já existente), a API retornava uma mensagem de erro enganadora, culpando sempre o CPF.
- Solução Implementada:
- O bloco except IntegrityError foi aprimorado para inspecionar a mensagem de erro original da base de dados (e.orig). Isto permite que a API retorne uma mensagem de erro específica e correta, diferenciando entre um CPF duplicado e outra violação de integridade, como um nome duplicado.
- Framework: FastAPI
- Base de Dados: PostgreSQL (a correr num container Docker)
- ORM: SQLAlchemy (com suporte asyncio)
- Gestão de Migrações: Alembic
- Validação de Dados: Pydantic
- Servidor ASGI: Uvicorn
- Automação: Make
- Ambiente: Pyenv, Venv
- Ferramentas de Teste: Postman, DBeaver
Durante o desenvolvimento, foram implementadas as seguintes funcionalidades específicas do desafio:
- O endpoint
GET /atletas
permite filtrar atletas pornome
ecpf
via query string. - Exemplo:
/atletas?nome=Joao&cpf=12345678900
- A resposta do endpoint
GET /atletas
foi ajustada para retornar apenas os campos:nome
categoria
centro_treinamento
- Isso foi feito utilizando o schema
AtletaListOut
.
- O endpoint
POST /atletas
captura exceções do tipoIntegrityError
(SQLAlchemy). - Quando um CPF duplicado é enviado, a API retorna:
- Status code:
303
- Mensagem:
"Já existe um atleta cadastrado com esse código: 303"
- Status code:
- A biblioteca
fastapi-pagination
foi integrada ao projeto. - O endpoint
GET /atletas
agora suporta paginação comlimit
eoffset
. - Exemplo de resposta paginada:
{
"items": [...],
"total": 42,
"page": 1,
"size": 10
}