Перейти до змісту

Параметри шляху та валідація числових даних

Так само як ви можете оголошувати додаткові перевірки та метадані для query параметрів за допомогою Query, ви можете оголошувати той самий тип перевірок і метаданих для параметрів шляху за допомогою Path.

Імпорт Path

Спочатку імпортуйте Path з fastapi і імпортуйте Annotated:

from typing import Annotated

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")],
    q: Annotated[str | None, Query(alias="item-query")] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants
from typing import Annotated, Union

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")],
    q: Annotated[Union[str, None], Query(alias="item-query")] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get"),
    q: str | None = Query(default=None, alias="item-query"),
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Tip

Prefer to use the Annotated version if possible.

from typing import Union

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get"),
    q: Union[str, None] = Query(default=None, alias="item-query"),
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Інформація

FastAPI додав підтримку Annotated (і почав рекомендувати його використання) у версії 0.95.0.

Якщо у вас стара версія, при спробі використати Annotated можуть виникати помилки.

Переконайтеся, що ви оновили версію FastAPI принаймні до версії 0.95.1 перед використанням Annotated.

Оголошення метаданих

Ви можете оголошувати всі ті ж параметри, що і для Query.

Наприклад, щоб оголосити значення метаданих title для параметра шляху item_id, ви можете написати:

from typing import Annotated

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")],
    q: Annotated[str | None, Query(alias="item-query")] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants
from typing import Annotated, Union

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")],
    q: Annotated[Union[str, None], Query(alias="item-query")] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get"),
    q: str | None = Query(default=None, alias="item-query"),
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Tip

Prefer to use the Annotated version if possible.

from typing import Union

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get"),
    q: Union[str, None] = Query(default=None, alias="item-query"),
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Примітка

Параметр шляху завжди є обов’язковим, оскільки він має бути частиною шляху. Навіть якщо ви оголосите його зі значенням None або встановите значення за замовчуванням — це ні на що не вплине, він все одно завжди буде обов’язковим.

Упорядковуйте параметри, як вам потрібно

Порада

Це, мабуть, не настільки важливо або необхідно, якщо ви використовуєте Annotated.

Припустимо, ви хочете оголосити параметр запиту q як обов’язковий str.

І вам не потрібно оголошувати нічого іншого для цього параметра, тому вам насправді не потрібно використовувати Query.

Але вам все одно потрібно використовувати Path для параметра шляху item_id. І з певних причин ви не хочете використовувати Annotated.

Python видасть помилку, якщо розмістити значення з "default" перед значенням, яке не має "default".

Але ви можете змінити порядок і розмістити значення без значення за замовчуванням (параметр запиту q) першим.

Для FastAPI порядок не має значення. Він визначає параметри за їхніми іменами, типами та оголошеннями за замовчуванням (Query, Path тощо) і не звертає уваги на порядок.

Тому ви можете оголосити вашу функцію так:

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(q: str, item_id: int = Path(title="The ID of the item to get")):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants
from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    q: str, item_id: Annotated[int, Path(title="The ID of the item to get")]
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Але майте на увазі, що якщо ви використовуєте Annotated, цієї проблеми не буде, це не матиме значення, оскільки ви не використовуєте значення за замовчуванням параметрів функції для Query() або Path().

from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    q: str, item_id: Annotated[int, Path(title="The ID of the item to get")]
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(q: str, item_id: int = Path(title="The ID of the item to get")):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Упорядковуйте параметри, як вам потрібно: хитрощі

Порада

Це, мабуть, не настільки важливо або необхідно, якщо ви використовуєте Annotated.

Ось невелика хитрість, яка може стати в пригоді, хоча вона рідко знадобиться.

Якщо ви хочете:

  • оголосити параметр запиту q без Query і без жодного значення за замовчуванням
  • оголосити параметр шляху item_id, використовуючи Path
  • розмістити їх у різному порядку
  • не використовувати Annotated

...у Python є спеціальний синтаксис для цього.

Передайте * як перший параметр функції.

Python нічого не зробить із цією *, але розпізнає, що всі наступні параметри слід викликати як аргументи за ключовим словом (пари ключ-значення), також відомі як kwargs. Навіть якщо вони не мають значення за замовчуванням.

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(*, item_id: int = Path(title="The ID of the item to get"), q: str):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants
from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")], q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Краще з Annotated

Майте на увазі, що якщо ви використовуєте Annotated, оскільки ви не використовуєте значення за замовчуванням параметрів функції, цієї проблеми не буде, і, ймовірно, вам не потрібно буде використовувати *.

from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")], q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(*, item_id: int = Path(title="The ID of the item to get"), q: str):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Валідація числових даних: більше або дорівнює

За допомогою Query і Path (та інших, які ви побачите пізніше) можна оголошувати числові обмеження.

Тут, завдяки ge=1, item_id має бути цілим числом, яке "greater than or equal" (більше або дорівнює) 1.

from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)], q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    *, item_id: int = Path(title="The ID of the item to get", ge=1), q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Валідація числових даних: більше ніж і менше або дорівнює

Те саме застосовується до:

  • gt: greater than
  • le: less than or equal
from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get", gt=0, le=1000)],
    q: str,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    *,
    item_id: int = Path(title="The ID of the item to get", gt=0, le=1000),
    q: str,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Валідація числових даних: float, більше ніж і менше ніж

Валідація чисел також працює для значень типу float.

Ось де стає важливо мати можливість оголошувати gt, а не тільки ge. Це дозволяє, наприклад, вимагати, щоб значення було більше 0, навіть якщо воно менше 1.

Таким чином, значення 0.5 буде допустимим. Але 0.0 або 0 — ні.

Те саме стосується lt.

from typing import Annotated

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    *,
    item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],
    q: str,
    size: Annotated[float, Query(gt=0, lt=10.5)],
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    if size:
        results.update({"size": size})
    return results
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    *,
    item_id: int = Path(title="The ID of the item to get", ge=0, le=1000),
    q: str,
    size: float = Query(gt=0, lt=10.5),
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    if size:
        results.update({"size": size})
    return results

Підсумок

За допомогою Query, Path (і інших параметрів, які ви ще не бачили) можна оголошувати метадані та перевірки рядків так само як у Query параметри та валідація рядків.

Також можна оголошувати числові перевірки:

  • gt: greater than
  • ge: greater than or equal
  • lt: less than
  • le: less than or equal

Інформація

Query, Path та інші класи, які ви побачите пізніше, є підкласами спільного класу Param.

Всі вони мають однакові параметри для додаткових перевірок і метаданих, які ви вже бачили.

Технічні деталі

Коли ви імпортуєте Query, Path та інші з fastapi, насправді це функції.

При виклику вони повертають екземпляри класів з такими ж іменами.

Тобто ви імпортуєте Query, яка є функцією. А коли ви її викликаєте, вона повертає екземпляр класу, який теж називається Query.

Ці функції створені таким чином (замість використання класів напряму), щоб ваш редактор не відзначав їхні типи як помилки.

Таким чином, ви можете користуватися своїм звичайним редактором і інструментами для програмування без додаткових налаштувань для ігнорування таких помилок.