Capítulo 19: FastAPI com Banco de Dados (SQLite) 🦅🏛️
Neste capítulo, vamos juntar o FastAPI com o SQLite (que aprendemos no Capítulo 14) para criar uma API que busca dados reais em um banco de dados, com o tema Assassin’s Creed!
📖 Por que conectar a API ao Banco de Dados?
Até agora, nossas respostas do FastAPI eram fixas no código (hardcoded). Conectando a um banco de dados, podemos criar aplicações dinâmicas reais, onde os dados podem ser cadastrados, alterados e consultados via web!
📖 Exemplo Guiado: Registro do Animus
Vamos criar um banco de dados de assassinos e uma rota no FastAPI que busca um assassino pelo ID.
- Crie o arquivo
criar_banco.pyna pastasrc/para preparar os dados:
import sqlite3
def init_db():
conn = sqlite3.connect('animus.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS assassinos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nome TEXT,
epoca TEXT
)
''')
# Inserindo alguns dados de exemplo
cursor.execute("SELECT COUNT(*) FROM assassinos")
if cursor.fetchone()[0] == 0:
cursor.execute("INSERT INTO assassinos (nome, epoca) VALUES ('Altaïr', 'Terceira Cruzada')")
cursor.execute("INSERT INTO assassinos (nome, epoca) VALUES ('Ezio Auditore', 'Renascimento')")
cursor.execute("INSERT INTO assassinos (nome, epoca) VALUES ('Eivor', 'Era Viking')")
conn.commit()
conn.close()
if __name__ == '__main__':
init_db()
print("Banco animus.db criado e populado!")- Crie o arquivo
app_animus.pyna pastasrc/:
from fastapi import FastAPI, HTTPException
import sqlite3
app = FastAPI()
def busca_no_banco(id_assassino: int):
conn = sqlite3.connect('animus.db')
cursor = conn.cursor()
cursor.execute("SELECT * FROM assassinos WHERE id = ?", (id_assassino,))
resultado = cursor.fetchone()
conn.close()
return resultado
@app.get('/assassino/{id}')
def obter_assassino(id: int):
dados = busca_no_banco(id)
if dados:
# O FastAPI converte dicionários para JSON automaticamente!
return {
"id": dados[0],
"nome": dados[1],
"epoca": dados[2]
}
else:
# Forma correta de retornar erros no FastAPI
raise HTTPException(status_code=404, detail="Registro não encontrado no Animus")🕹️ Como Executar e Testar no VS Code
- Rode primeiro o
criar_banco.pypara criar o arquivo de banco de dados. - No terminal, execute:
uvicorn app_animus:app --reload - Acesse no navegador:
http://127.0.0.1:8000/assassino/2
Resultado Esperado no Navegador:
{
"epoca": "Renascimento",
"id": 2,
"nome": "Ezio Auditore"
}📊 Ilustração Visual: Fluxo FastAPI + DB
Veja o caminho que a informação faz:
graph LR A["🌐 Navegador"] -->|1. Pede ID 2| B["💻 API FastAPI"] B -->|2. Consulta SQL| C[(🗄️ SQLite: animus.db)] C -->|3. Retorna Linha| B B -->|4. Retorna JSON| A
🛠️ Prática Obrigatória 1: Listar Todos
Crie uma nova rota chamada /assassinos que busque todos os assassinos cadastrados no banco e os retorne em uma lista. (Dica: use cursor.execute("SELECT * FROM assassinos") e cursor.fetchall()). Lembre-se de retornar uma lista de dicionários!
🔑 Gabarito de Código
Prática 1: Nova rota no app_animus.py
@app.get('/assassinos')
def listar_todos():
conn = sqlite3.connect('animus.db')
cursor = conn.cursor()
cursor.execute("SELECT * FROM assassinos")
resultados = cursor.fetchall()
conn.close()
lista = []
for r in resultados:
lista.append({"id": r[0], "nome": r[1], "epoca": r[2]})
return lista📤 Instruções de Entrega (GitHub Desktop + Microsoft Teams)
(Siga o mesmo padrão do Capítulo 01)