SQLModel / SQLAlchemy
SQLAlchemy é o kit de ferramentas SQL e ORM fundamental do Python. SQLModel (do autor do FastAPI) adiciona validação Pydantic sobre modelos SQLAlchemy para esquemas amigáveis à API. Esta página orienta sobre o essencial - a seção de bancos de dados aborda mais profundamente.
Receita
from sqlmodel import Field, Session, SQLModel, create_engine, select
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
secret_name: str
engine = create_engine("sqlite:///heroes.db")
SQLModel.metadata.create_all(engine)
with Session(engine) as session:
session.add(Hero(name="Deadpond", secret_name="Dive"))
session.commit()
heroes = session.exec(select(Hero)).all()Quando usar isso:
- Serviços FastAPI persistindo em Postgres/MySQL/SQLite
- Compartilhamento de tipos entre linhas de banco de dados e modelos de resposta de API
- Consultas complexas que necessitam do poder de expressão do SQLAlchemy
- Scripts adjacentes ao Django que ainda precisam de controle SQL bruto
Exemplo de Trabalho
from __future__ import annotations
from sqlmodel import Field, Session, SQLModel, create_engine, select
class Book(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
title: str
author: str
published_year: int
def seed(engine) -> None:
with Session(engine) as session:
session.add(Book(title="Neuromancer", author="Gibson", published_year=1984))
session.commit()
def list_recent(engine, min_year: int) -> list[Book]:
with Session(engine) as session:
statement = select(Book).where(Book.published_year >= min_year).order_by(Book.title)
return list(session.exec(statement))
if __name__ == "__main__":
engine = create_engine("sqlite:///:memory:")
SQLModel.metadata.create_all(engine)
seed(engine)
print(list_recent(engine, 1980))O que isso demonstra:
- Uma única classe serve como tabela ORM e modelo validado
- SQLAlchemy 2.0
select()+session.exec - Sessão por unidade de trabalho com commit explícito
- SQLite em memória para exemplo executável
Mergulho Profundo
Como Funciona
- Engine - Pool de conexões para a URL do banco de dados.
- Session - Unidade de trabalho rastreando objetos modificados;
commit/rollback. - SQLModel -
table=Trueregistra o mapeamento ORM; sem isso, a classe é um DTO apenas Pydantic. - SQLAlchemy Core -
Table,insert(),update()quando o ORM é muito pesado.
SQLModel vs SQLAlchemy Puro
| Abordagem | Melhor Para |
|---|---|
| SQLModel | CRUD FastAPI, tipos de API/DB compartilhados |
| SQLAlchemy declarativo | Grandes domínios, Core/ORM mistos |
| Django ORM | Monólitos Django |
Notas Python
# Modelos de leitura vs escrita em aplicativos maiores
class BookCreate(SQLModel):
title: str
author: str
class BookRead(BookCreate):
id: intArmadilhas
create_allem produção - Sem histórico de migração. Correção: Revisões Alembic.- Consultas N+1 - Carregamento preguiçoso em loops. Correção:
selectinloadou joins explícitos. - Suposições do SQLite em produção - Diferente do bloqueio/tipos do Postgres. Correção: testar contra o engine de produção em CI.
- Compartilhar sessão entre requisições - Condições de corrida. Correção: sessão por requisição via dependência do FastAPI.
- Nulável sem
Optional- Dicas de tipo mentem. Correção:str | Nonecorresponde a colunas nuláveis. - Tabela gigante do SQLModel - API vaza colunas do DB. Correção: esquemas
Read/Createseparados.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Django ORM | Django é o framework web | Microserviço FastAPI autônomo |
psycopg SQL puro | Consultas de relatório, COPY em massa | Modelo de domínio rico com relacionamentos |
| Tortoise ORM | Aplicativos menores com foco em assíncrono | Ecossistema SQLAlchemy maduro necessário |
| Peewee | Scripts minúsculos | Pooling de conexão em escala |
FAQs
SQLModel ou SQLAlchemy sozinho?
SQLModel para CRUD novo em FastAPI; use padrões SQLAlchemy quando as consultas excederem a ergonomia do ORM.
Como funcionam as migrações?
Use Alembic para autogerar a partir dos metadados - veja Alembic.
Sessões assíncronas?
AsyncSession do SQLAlchemy 2.0 com asyncpg - rotas assíncronas do FastAPI não devem bloquear em sessões síncronas.
Como faço paginação?
select(Book).offset(skip).limit(limit) - adicione uma chave de ordenação estável; considere paginação por cursor para tabelas grandes.
Carregamento de relacionamento?
Defina campos Relationship(); use selectinload na consulta para carregar antecipadamente.
SQLModel funciona com Pydantic v2?
Sim, nas pilhas atuais fixadas neste cookbook - valide as notas de atualização ao atualizar qualquer uma das bibliotecas.
Como testar código de DB?
Rollbacks de transação por fixture de teste ou SQLite :memory: com create_all por módulo de teste.
String de conexão do env?
Carregue DATABASE_URL via pydantic-settings.
Escape hatch para SQL puro?
session.exec(text("SELECT ...")) para relatórios - ainda vincule parâmetros, nunca use f-string SQL.
Django e SQLAlchemy juntos?
Possível em migrações híbridas, mas complicado - escolha um ORM por contexto delimitado.
Relacionados
- Noções Básicas de Bancos de Dados - cobertura profunda da camada de dados
- Alembic - migrações de esquema
- Rotas Assíncronas e Bancos de Dados do FastAPI - padrões AsyncSession
- Modelos e o ORM do Django - alternativa de framework
Versões da Pilha: Esta página foi escrita para Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, e uv 0.6+.