Paginação no SQLAlchemy com limit, offset e cursor resolve um problema recorrente em projetos Python: Entregue resultados em páginas previsíveis sem repetir ou omitir linhas. Este guia mostra o mecanismo, um exemplo executável e os limites que evitam uma implementação frágil.
Conceito e caso de uso
Offset é simples para volumes pequenos; cursor usa a última chave ordenada e escala melhor em tabelas grandes.
Para revisar os fundamentos relacionados, consulte também o guia de SQLAlchemy. A integração fica mais simples quando cada função recebe dependências e dados explicitamente, em vez de depender de estado global.
Exemplo prático
stmt = select(Post).where(Post.published.is_(True)).order_by(Post.created_at.desc(), Post.id.desc()).limit(21)
rows = session.scalars(stmt).all()
has_next = len(rows) > 20
items = rows[:20]
Toda paginação exige uma ordenação total e estável, normalmente com a chave primária como desempate.
Decisões importantes
A escolha correta depende do contrato público, do volume e do comportamento em caso de falha.
Considere como a solução se comporta sob concorrência, entradas vazias e falhas parciais. Documente qualquer limite que afete consumidores e mantenha nomes que expressem a intenção.
Erros comuns
O exemplo mínimo não substitui limites, tratamento de erros e observabilidade. Sem order_by, a ordem não é garantida. Offset alto pode percorrer muitas linhas e mudanças concorrentes deslocam resultados.
Evite capturar exceções sem contexto ou retornar resultados parciais como se fossem completos. Uma falha explícita costuma ser mais segura que dados silenciosamente incorretos.
Como validar
Valide o comportamento, não apenas a linha feliz. Teste empates, última página, inserções entre requisições e limites máximos aceitos pela API.