Especialização em Backend com Python & FastAPI • FastAPI & Python 3.12+ • Pydantic v2, SQLModel, Async/Await e Microsserviços


🗺️ Mapa Conceitual do Tópico

flowchart TD
    A["Cliente HTTP / Frontend"] --> B["API Gateway / Router"]
    B --> C["Controller / Handler"]
    C --> D["Service Layer (Regras de Negócio)"]
    D --> E["Repository / ORM (Persistência)"]
    E --> F["Banco de Dados / Cache"]

    subgraph ARQ["Arquitetura do Capítulo"]
        G["Conceito: Injeção de Dependências no FastAPI (Depends, Annotated)"]
        H["Segurança, Validação e Resiliência"]
        I["Alta Performance e Escalabilidade"]
    end

    D --> ARQ

    style A fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px
    style B fill:#fff3e0,stroke:#ff9800,stroke-width:2px
    style C fill:#ede7f6,stroke:#7e57c2,stroke-width:2px
    style D fill:#e8f5e9,stroke:#4caf50,stroke-width:2px
    style E fill:#fce4ec,stroke:#e91e63,stroke-width:2px
    style F fill:#f3e5f5,stroke:#9c27b0,stroke-width:2px

🏛️ 1. Depends como padrão de Injeção de Dependências

O sistema de dependências do FastAPI é o mecanismo que permite compartilhar lógica reutilizável entre endpoints — autenticação, paginação, conexões de banco, filtros — sem duplicar código nem acoplar handlers diretamente a implementações concretas. Uma dependência é simplesmente uma função ou classe chamável (callable) que o FastAPI executa antes do handler e cujo valor de retorno é injetado como parâmetro. A grande vantagem sobre chamar a função diretamente dentro do endpoint é que Depends participa do sistema de validação e documentação automática do OpenAPI, e pode ser sobrescrita em testes via app.dependency_overrides, sem precisar de mocks complexos.

from typing import Annotated
from fastapi import FastAPI, Depends, Query

app = FastAPI()

def obter_paginacao(
    skip: Annotated[int, Query(ge=0)] = 0,
    limit: Annotated[int, Query(ge=1, le=100)] = 20,
) -> dict:
    return {"skip": skip, "limit": limit}

@app.get("/artigos")
async def listar_artigos(pag: Annotated[dict, Depends(obter_paginacao)]):
    return {"pagina": pag, "itens": []}

A forma Annotated[Tipo, Depends(...)] é a sintaxe recomendada desde o FastAPI 0.95: ela separa o tipo da metainformação de origem do valor, o que é reaproveitável em múltiplos parâmetros e compatível com ferramentas de análise estática de tipos, ao contrário do antigo param: Tipo = Depends(...).

Dependências baseadas em classe

Quando a dependência precisa manter múltiplos atributos relacionados (não apenas um valor único), uma classe é mais expressiva que uma função. Depends() sem argumento, aplicado a um parâmetro anotado com a própria classe, instrui o FastAPI a instanciar a classe usando seu __init__ como se fosse a assinatura da dependência — cada parâmetro do construtor vira um query parameter validado automaticamente.

from typing import Optional
from fastapi import FastAPI, Depends

class FiltroAuditoria:
    def __init__(self, autor: Optional[str] = None, status: str = "ATIVO"):
        self.autor = autor
        self.status = status

app = FastAPI()

@app.get("/logs")
async def buscar_logs(filtro: FiltroAuditoria = Depends()):
    return {"autor_filtrado": filtro.autor, "status": filtro.status}

Sub-dependências (dependências encadeadas)

Dependências podem depender de outras dependências, formando uma árvore de resolução que o FastAPI resolve automaticamente, de baixo para cima. Isso viabiliza pipelines de autenticação em camadas: extrair o token do header, validar o token, e só então carregar o usuário — cada etapa isolada e testável separadamente.

from fastapi import FastAPI, Depends, HTTPException, Header

app = FastAPI()

def obter_token(authorization: str = Header(...)) -> str:
    if not authorization.startswith("Bearer "):
        raise HTTPException(status_code=401)
    return authorization.split(" ")[1]

def obter_usuario_logado(token: str = Depends(obter_token)) -> dict:
    if token != "secret_token_123":
        raise HTTPException(status_code=403)
    return {"user_id": 101, "role": "ADMIN"}

@app.get("/me")
async def get_me(current_user: dict = Depends(obter_usuario_logado)):
    return {"usuario": current_user}

Por padrão, o FastAPI faz cache do resultado de uma dependência dentro do escopo de uma única requisição — se duas rotas ou dois parâmetros do mesmo endpoint dependem de obter_token, a função roda apenas uma vez. Esse comportamento pode ser desligado com Depends(obter_token, use_cache=False) quando o valor precisa ser recalculado (por exemplo, um timestamp de auditoria).

Dependências com yield: setup e teardown garantidos

Quando a dependência precisa liberar um recurso depois que a resposta é enviada (fechar uma sessão de banco, devolver uma conexão a um pool), usa-se yield em vez de return. O código antes do yield roda como setup; o código depois — dentro de um try/finally — roda como teardown, mesmo que o handler levante uma exceção, garantindo que a sessão nunca vaze.

from fastapi import FastAPI, Depends

app = FastAPI()

async def get_db_session():
    print("LOG: Conexão com banco aberta")
    db = {"status": "conectado", "id": 42}
    try:
        yield db
    finally:
        print("LOG: Conexão com banco encerrada com sucesso")

@app.get("/transacao")
async def executar_transacao(db: dict = Depends(get_db_session)):
    return {"db_id": db["id"], "resultado": "OK"}

🔗 Recursos Pedagógicos do Capítulo 04

Recurso Didático Finalidade Link de Acesso
📊 Slides de Aula Apresentação visual interativa com Dark Mode e suporte a teclado Ver Slides
🧠 Quiz Formativo Teste interativo de fixação com feedback imediato por alternativa Fazer Quiz
💻 Exemplos de Código Demonstrações funcionais com código executável Ver Exemplos
🧩 Exercícios em 4 Níveis Lista progressiva de fixação com gabarito em bloco colapsável Resolver Exercícios

⬅️ Capítulo Anterior 📚 Sumário de Tópicos Próximo Capítulo ➡️