Короткий ответ
Пагинация — разбиение большого списка ресурсов на меньшие порции (страницы), которые клиент запрашивает по очереди; она нужна, чтобы не возвращать весь набор данных за один запрос, что перегружает память сервера, сеть и клиента.
Как это работает подробнее
клиент передаёт параметры (например, page/per_page или limit/offset), сервер ограничивает выборку с помощью LIMIT/OFFSET в SQL (или аналога в ORM) и возвращает только часть данных плюс метаданные (общее количество, наличие следующей страницы).
Пример кода
example.py
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items")
def list_items(page: int = Query(1, ge=1), per_page: int = Query(20, ge=1, le=100)):
offset = (page - 1) * per_page
rows = db_session.execute(
"SELECT id, name FROM items ORDER BY id LIMIT :limit OFFSET :offset",
{"limit": per_page, "offset": offset},
).fetchall()
return {"page": page, "per_page": per_page, "items": [dict(r) for r in rows]}Что использовать на практике
- Рекомендация. без пагинации по умолчанию эндпоинт списка легко превращается в "выгрузить всю таблицу", что при росте данных рано или поздно приведёт к деградации производительности и таймаутам. Лимит страницы стоит ограничивать сверху (например, максимум 100), чтобы клиент не мог запросить миллион записей одним вызовом.
Подводные камни
- Риски. не задавать значение по умолчанию и максимум для размера страницы, из-за чего один клиент может перегрузить сервис; возвращать общее количество через
COUNT(*)по всей таблице при каждом запросе страницы без необходимости, что само по себе может быть дорогим на больших таблицах.