Модели Query-Параметров¶
🌐 Перевод выполнен с помощью ИИ и людей
Этот перевод был сделан ИИ под руководством людей. 🤝
В нем могут быть ошибки из-за неправильного понимания оригинального смысла или неестественности и т. д. 🤖
Вы можете улучшить этот перевод, помогая нам лучше направлять ИИ LLM.
Если у вас есть группа связанных query-параметров, то вы можете объединить их в одну Pydantic-модель.
Это позволит вам переиспользовать модель в разных местах, объявлять правила валидации и метаданные сразу для всех параметров. 😎
Заметка
Это поддерживается начиная с версии FastAPI 0.115.0. 🤓
Pydantic-Модель для Query-Параметров¶
Объявите нужные query-параметры в Pydantic-модели, а после объявите параметр как Query:
from typing import Annotated, Literal
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class FilterParams(BaseModel):
limit: int = Field(100, gt=0, le=100)
offset: int = Field(0, ge=0)
order_by: Literal["created_at", "updated_at"] = "created_at"
tags: list[str] = []
@app.get("/items/")
async def read_items(filter_query: Annotated[FilterParams, Query()]):
return filter_query
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
from typing import Literal
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class FilterParams(BaseModel):
limit: int = Field(100, gt=0, le=100)
offset: int = Field(0, ge=0)
order_by: Literal["created_at", "updated_at"] = "created_at"
tags: list[str] = []
@app.get("/items/")
async def read_items(filter_query: FilterParams = Query()):
return filter_query
FastAPI извлечёт данные, соответствующие каждому полю модели, из query-параметров HTTP-запроса и выдаст вам объявленную Pydantic-модель, заполненную ими.
Проверьте Сгенерированную Документацию¶
Вы можете посмотреть query-параметры в графическом интерфейсе сгенерированной документации по пути /docs:
Запретить Дополнительные Query-Параметры¶
В некоторых случаях (не особо часто встречающихся) вам может понадобиться ограничить query-параметры, которые вы хотите получить.
Вы можете сконфигурировать Pydantic-модель так, чтобы запретить (forbid) все дополнительные (extra) поля:
from typing import Annotated, Literal
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class FilterParams(BaseModel):
model_config = {"extra": "forbid"}
limit: int = Field(100, gt=0, le=100)
offset: int = Field(0, ge=0)
order_by: Literal["created_at", "updated_at"] = "created_at"
tags: list[str] = []
@app.get("/items/")
async def read_items(filter_query: Annotated[FilterParams, Query()]):
return filter_query
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
from typing import Literal
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class FilterParams(BaseModel):
model_config = {"extra": "forbid"}
limit: int = Field(100, gt=0, le=100)
offset: int = Field(0, ge=0)
order_by: Literal["created_at", "updated_at"] = "created_at"
tags: list[str] = []
@app.get("/items/")
async def read_items(filter_query: FilterParams = Query()):
return filter_query
Если клиент попробует отправить дополнительные данные в query-параметрах, то он получит HTTP-ответ с ошибкой.
Например, если клиент попытается отправить query-параметр tool со значением plumbus, в виде:
https://example.com/items/?limit=10&tool=plumbus
То он получит HTTP-ответ с ошибкой, сообщающей ему, что query-параметр tool не разрешен:
{
"detail": [
{
"type": "extra_forbidden",
"loc": ["query", "tool"],
"msg": "Extra inputs are not permitted",
"input": "plumbus"
}
]
}
Комбинирование Моделей Параметров¶
Вы можете объявить несколько моделей query-параметров и комбинировать их с отдельными query-параметрами или зависимостями.
from typing import Annotated
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class Pagination(BaseModel):
limit: int = Field(10, ge=1)
offset: int = Field(0, ge=0)
class Filters(BaseModel):
tags: list[str] = []
@app.get("/items/")
def read_items(
pagination: Annotated[Pagination, Query()],
filters: Annotated[Filters, Query()],
search: str | None = None,
):
return {"pagination": pagination, "filters": filters, "search": search}
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class Pagination(BaseModel):
limit: int = Field(10, ge=1)
offset: int = Field(0, ge=0)
class Filters(BaseModel):
tags: list[str] = []
@app.get("/items/")
def read_items(
pagination: Pagination = Query(),
filters: Filters = Query(),
search: str | None = None,
):
return {"pagination": pagination, "filters": filters, "search": search}
Параметры HTTP-запроса остаются на одном уровне.
https://example.com/items/?limit=5&offset=10&tags=red&tags=blue&search=shirt
В строке запроса нет ключей pagination или filters. Каждая модель независимо валидирует query-параметры, используя собственные значения по умолчанию, валидаторы полей и валидаторы модели. То же самое происходит, когда модели или отдельные параметры объявлены в зависимостях.
Если модели используют одно и то же имя или псевдоним параметра, каждая модель независимо валидирует этот параметр HTTP-запроса. Используйте разные имена или псевдонимы для независимых значений. OpenAPI отображает общий параметр один раз, как и в случае параметров, общих с зависимостями, поэтому объявления общего параметра должны описывать одинаковые тип и ограничения.
Настройка extra каждой модели применяется ко всем query-параметрам, включая объявленные в других моделях или зависимостях. При extra="forbid" любой параметр, не входящий в эту модель, отклоняется. При extra="allow" такие параметры включаются в модель как дополнительные поля.
Это также работает для моделей Header и Cookie.
Необязательные Модели Query-Параметров¶
Объявите модель query-параметров с | None и значением по умолчанию None, чтобы сделать группу необязательной.
from datetime import date
from typing import Annotated
from fastapi import FastAPI, Query
from pydantic import BaseModel
app = FastAPI()
class DateRange(BaseModel):
start: date
end: date
@app.get("/items/")
async def read_items(
limit: int = 10,
date_range: Annotated[DateRange | None, Query()] = None,
):
return {"limit": limit, "date_range": date_range}
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
from datetime import date
from fastapi import FastAPI, Query
from pydantic import BaseModel
app = FastAPI()
class DateRange(BaseModel):
start: date
end: date
@app.get("/items/")
async def read_items(
limit: int = 10,
date_range: DateRange | None = Query(default=None),
):
return {"limit": limit, "date_range": date_range}
Если ни start, ни end не переданы, date_range равен None. Если передан хотя бы один из них, FastAPI валидирует модель и требует оба поля.
При использовании | None без значения по умолчанию параметр остаётся обязательным.
Дополнительные параметры обрабатываются согласно настройке extra модели. Игнорируемые дополнительные параметры не приводят к созданию экземпляра модели.
OpenAPI отображает поля группы по отдельности и помечает их как необязательные.
Вы также можете объявлять необязательные модели параметров HTTP-заголовков и модели cookie-параметров.
Заключение¶
Вы можете использовать Pydantic-модели для объявления query-параметров в FastAPI. 😎
Совет
Спойлер: вы также можете использовать Pydantic-модели, чтобы объявлять cookies и HTTP-заголовки, но об этом вы прочитаете позже в руководстве. 🤫