Перейти к содержанию

Query-параметры

Когда вы объявляете параметры функции, которые не являются параметрами пути, они автоматически интерпретируются как "query"-параметры.

from fastapi import FastAPI

app = FastAPI()

fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]


@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
    return fake_items_db[skip : skip + limit]

Query-параметры представляют из себя набор пар ключ-значение, которые идут после знака ? в URL-адресе, разделенные символами &.

Например, в этом URL-адресе:

http://127.0.0.1:8000/items/?skip=0&limit=10

...параметры запроса такие:

  • skip: со значением 0
  • limit: со значением 10

Будучи частью URL-адреса, они "по умолчанию" являются строками.

Но когда вы объявляете их с использованием типов Python (в примере выше, как int), они конвертируются в указанный тип данных и проходят проверку на соответствие ему.

Все те же правила, которые применяются к path-параметрам, также применяются и query-параметрам:

  • Поддержка от редактора кода (очевидно)
  • "Парсинг" данных
  • Проверка на соответствие данных (Валидация)
  • Автоматическая документация

Значения по умолчанию

Поскольку query-параметры не являются фиксированной частью пути, они могут быть не обязательными и иметь значения по умолчанию.

В примере выше значения по умолчанию равны skip=0 и limit=10.

Таким образом, результат перехода по URL-адресу:

http://127.0.0.1:8000/items/

будет таким же, как если перейти используя параметры по умолчанию:

http://127.0.0.1:8000/items/?skip=0&limit=10

Но если вы введёте, например:

http://127.0.0.1:8000/items/?skip=20

Значения параметров в вашей функции будут:

  • skip=20: потому что вы установили это в URL-адресе
  • limit=10: т.к это было значение по умолчанию

Необязательные параметры

Аналогично, вы можете объявлять необязательные query-параметры, установив их значение по умолчанию, равное None:

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: str, q: str | None = None):
    if q:
        return {"item_id": item_id, "q": q}
    return {"item_id": item_id}
🤓 Other versions and variants
from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: str, q: Union[str, None] = None):
    if q:
        return {"item_id": item_id, "q": q}
    return {"item_id": item_id}

В этом случае, параметр q будет не обязательным и будет иметь значение None по умолчанию.

Важно

Также обратите внимание, что FastAPI достаточно умён чтобы заметить, что параметр item_id является path-параметром, а q нет, поэтому, это параметр запроса.

Преобразование типа параметра запроса

Вы также можете объявлять параметры с типом bool, которые будут преобразованы соответственно:

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: str, q: str | None = None, short: bool = False):
    item = {"item_id": item_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item
🤓 Other versions and variants
from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: str, q: Union[str, None] = None, short: bool = False):
    item = {"item_id": item_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item

В этом случае, если вы сделаете запрос:

http://127.0.0.1:8000/items/foo?short=1

или

http://127.0.0.1:8000/items/foo?short=True

или

http://127.0.0.1:8000/items/foo?short=true

или

http://127.0.0.1:8000/items/foo?short=on

или

http://127.0.0.1:8000/items/foo?short=yes

или в любом другом варианте написания (в верхнем регистре, с заглавной буквой, и т.п), внутри вашей функции параметр short будет иметь значение True типа данных bool . В противном случае - False.

Смешивание query-параметров и path-параметров

Вы можете объявлять несколько query-параметров и path-параметров одновременно, FastAPI сам разберётся, что чем является.

И вы не обязаны объявлять их в каком-либо определенном порядке.

Они будут обнаружены по именам:

from fastapi import FastAPI

app = FastAPI()


@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(
    user_id: int, item_id: str, q: str | None = None, short: bool = False
):
    item = {"item_id": item_id, "owner_id": user_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item
🤓 Other versions and variants
from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(
    user_id: int, item_id: str, q: Union[str, None] = None, short: bool = False
):
    item = {"item_id": item_id, "owner_id": user_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item

Обязательные query-параметры

Когда вы объявляете значение по умолчанию для параметра, который не является path-параметром (в этом разделе, мы пока что познакомились только с path-параметрами), то он не является обязательным.

Если вы не хотите задавать конкретное значение, но хотите сделать параметр необязательным, вы можете установить значение по умолчанию равным None.

Но если вы хотите сделать query-параметр обязательным, вы можете просто не указывать значение по умолчанию:

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_user_item(item_id: str, needy: str):
    item = {"item_id": item_id, "needy": needy}
    return item

Здесь параметр запроса needy является обязательным параметром с типом данных str.

Если вы откроете в браузере URL-адрес, например:

http://127.0.0.1:8000/items/foo-item

...без добавления обязательного параметра needy, вы увидите подобного рода ошибку:

{
  "detail": [
    {
      "type": "missing",
      "loc": [
        "query",
        "needy"
      ],
      "msg": "Field required",
      "input": null
    }
  ]
}

Поскольку needy является обязательным параметром, вам необходимо указать его в URL-адресе:

http://127.0.0.1:8000/items/foo-item?needy=sooooneedy

...это будет работать:

{
    "item_id": "foo-item",
    "needy": "sooooneedy"
}

Конечно, вы можете определить некоторые параметры как обязательные, некоторые — со значением по умолчанию, а некоторые — полностью необязательные:

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_user_item(
    item_id: str, needy: str, skip: int = 0, limit: int | None = None
):
    item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
    return item
🤓 Other versions and variants
from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_user_item(
    item_id: str, needy: str, skip: int = 0, limit: Union[int, None] = None
):
    item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
    return item

В этом примере, у нас есть 3 параметра запроса:

  • needy, обязательный str.
  • skip, типа int и со значением по умолчанию 0.
  • limit, необязательный int.

Подсказка

Вы можете использовать класс Enum также, как ранее применяли его с Path-параметрами.