Construindo uma API REST do zero com FastAPI
API REST completa com FastAPI: validação com Pydantic, CRUD e conexão com banco de dados
FastAPI é o framework mais rápido para construir APIs em Python. Validação automática de dados, documentação interativa gerada automaticamente e suporte nativo a async — tudo isso sem configuração extra. Vamos construir uma API de tarefas completa do zero.
Instalação
pip install fastapi uvicorn[standard]
Hello World
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def raiz():
return {"mensagem": "API funcionando"}
uvicorn main:app --reload
Acesse http://localhost:8000/docs — a documentação interativa já está lá, gerada automaticamente.
Modelos com Pydantic
Pydantic valida os dados de entrada automaticamente. Se o cliente mandar o tipo errado, a API já retorna um erro 422 com detalhes sem você escrever nenhuma validação manual.
from pydantic import BaseModel
from typing import Optional
class Tarefa(BaseModel):
titulo: str
descricao: Optional[str] = None
concluida: bool = False
class TarefaResposta(Tarefa):
id: int
CRUD completo
from fastapi import FastAPI, HTTPException
app = FastAPI()
db: dict[int, dict] = {}
contador = 0
@app.post("/tarefas/", response_model=TarefaResposta, status_code=201)
def criar_tarefa(tarefa: Tarefa):
global contador
contador += 1
db[contador] = tarefa.model_dump()
db[contador]["id"] = contador
return db[contador]
@app.get("/tarefas/", response_model=list[TarefaResposta])
def listar_tarefas():
return list(db.values())
@app.get("/tarefas/{id}", response_model=TarefaResposta)
def buscar_tarefa(id: int):
if id not in db:
raise HTTPException(status_code=404, detail="Tarefa não encontrada")
return db[id]
@app.put("/tarefas/{id}", response_model=TarefaResposta)
def atualizar_tarefa(id: int, dados: Tarefa):
if id not in db:
raise HTTPException(status_code=404, detail="Tarefa não encontrada")
db[id].update(dados.model_dump())
return db[id]
@app.delete("/tarefas/{id}", status_code=204)
def remover_tarefa(id: int):
if id not in db:
raise HTTPException(status_code=404, detail="Tarefa não encontrada")
del db[id]
Parâmetros de query e path
@app.get("/tarefas/")
def listar_tarefas(
concluida: Optional[bool] = None, # query param: /tarefas/?concluida=true
limite: int = 10,
pagina: int = 1,
):
resultado = list(db.values())
if concluida is not None:
resultado = [t for t in resultado if t["concluida"] == concluida]
inicio = (pagina - 1) * limite
return resultado[inicio:inicio + limite]
Conectando ao banco com SQLModel
pip install sqlmodel
from sqlmodel import SQLModel, Field, Session, create_engine, select
class Tarefa(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
titulo: str
concluida: bool = False
engine = create_engine("sqlite:///tarefas.db")
SQLModel.metadata.create_all(engine)
@app.post("/tarefas/")
def criar_tarefa(tarefa: Tarefa):
with Session(engine) as session:
session.add(tarefa)
session.commit()
session.refresh(tarefa)
return tarefa
SQLModel é feito pelo mesmo criador do FastAPI e combina Pydantic + SQLAlchemy num modelo único — você define o schema e o model de banco na mesma classe.
Próximos passos
Com a API no ar, o próximo passo é entender como usar async para servir muitas requisições simultâneas sem travar — é o que o tutorial de async/await cobre.