MiddleКодИногдаЕщё не отвечали
Переиспользуемая зависимость пагинации с проверкой границ
Нескольким списочным эндпоинтам нужны одни и те же query-параметры limit и offset. Напишите одну переиспользуемую зависимость, отдающую оба, чтобы каждый эндпоинт объявлял её одним аргументом вместо повторения параметров.
Требования:
не проверяйте и не подрезайте их внутри обработчика
limitпо умолчанию20и обязан оставаться в диапазоне1..100offsetпо умолчанию0и никогда не может быть отрицательным- значения вне диапазона отклоняет сам FastAPI кодом
422до запуска эндпоинта —
from fastapi import Depends, FastAPI, Query
app = FastAPI()
def pagination(...):
# ваш код здесь
...
@app.get("/items")
def list_items(page=Depends(pagination)):
return {"page": page}Допишите реализацию.
Объявите limit и offset обычными параметрами простой функции с границами Query(ge=..., le=...) и верните их. FastAPI разрешает собственные параметры зависимости ровно так же, как параметры эндпоинта, поэтому границы проверяются до запуска обработчика, а плохое значение даёт 422.
- ✗Читать строку запроса руками вместо объявления параметров у зависимости
- ✗Молча подрезать значения вне диапазона вместо того, чтобы дать
422их отклонить - ✗Считать, что
geиleвQuery()нужны только документации
- →Как раздать эту зависимость на каждый маршрут роутера?
- →Что изменится, если двум эндпоинтам нужны разные потолки
limit?
Оглавление
Задача
Вынесите limit и offset в одну зависимость так, чтобы границы проверял сам FastAPI, а эндпоинт объявлял пагинацию одним аргументом.
Решение
from typing import Annotated
from fastapi import Depends, FastAPI, Query
app = FastAPI()
def pagination(
limit: Annotated[int, Query(ge=1, le=100)] = 20,
offset: Annotated[int, Query(ge=0)] = 0,
) -> dict[str, int]:
return {"limit": limit, "offset": offset}
# псевдоним типа: объявление пагинации сжимается до одной аннотации
PageParams = Annotated[dict[str, int], Depends(pagination)]
@app.get("/items")
def list_items(page: PageParams):
return {"page": page}
@app.get("/orders")
def list_orders(page: PageParams):
return {"page": page}Ключевые моменты
- Параметры зависимости разрешаются тем же механизмом, что и параметры эндпоинта, поэтому
Query(ge=..., le=...)работает здесь ровно так же. - ⚠️
?limit=500даёт422со списком ошибок по полям до входа в обработчик — подрезать значение не нужно и вредно: клиент не узнает, что его параметр проигнорировали. - Псевдоним
Annotated[..., Depends(...)]убирает= Depends(pagination)из каждой сигнатуры и оставляет одну аннотацию на эндпоинт. - Результат зависимости кэшируется на время запроса, поэтому две под-зависимости, запросившие пагинацию, получат один и тот же объект.
Оглавление