Path Параметри та валідація числових даних¶
Так само як Ви можете оголошувати додаткові перевірки та метадані для 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
from typing import Union
from fastapi import FastAPI, Path, Query
from typing_extensions import Annotated
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
from typing import Union
from fastapi import FastAPI, Path, Query
from typing_extensions import Annotated
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
тощо) і не звертає уваги на порядок.
Тому Ви можете оголосити Вашу функцію так:
Підказка
За можливості віддавайте перевагу версії з використанням Annotated
.
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
from fastapi import FastAPI, Path
from typing_extensions import Annotated
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
from fastapi import FastAPI, Path
from typing_extensions import Annotated
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
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
from fastapi import FastAPI, Path
from typing_extensions import Annotated
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
from fastapi import FastAPI, Path
from typing_extensions import Annotated
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
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
має бути цілим числом, яке "g
reater than or e
qual" (більше або дорівнює) 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
from fastapi import FastAPI, Path
from typing_extensions import Annotated
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
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
:g
reatert
han (більше ніж)le
:l
ess than ore
qual (менше або дорівнює)
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
from fastapi import FastAPI, Path
from typing_extensions import Annotated
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
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
from fastapi import FastAPI, Path, Query
from typing_extensions import Annotated
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
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
:g
reatert
han (більше ніж)ge
:g
reater than ore
qual (більше або дорівнює)lt
:l
esst
han (менше ніж)le
:l
ess than ore
qual (менше або дорівнює)
Інформація
Query
, Path
та інші класи, які Ви побачите пізніше, є підкласами спільного класу Param
.
Всі вони мають однакові параметри для додаткових перевірок і метаданих, які Ви вже бачили.
Технічні деталі
Коли Ви імпортуєте Query
, Path
та інші з fastapi
, насправді це функції.
При виклику вони повертають екземпляри класів з такими ж іменами.
Тобто Ви імпортуєте Query
, яка є функцією. А коли Ви її викликаєте, вона повертає екземпляр класу, який теж називається Query
.
Ці функції створені таким чином (замість використання класів напряму), щоб Ваш редактор не відзначав їхні типи як помилки.
Таким чином, Ви можете користуватися своїм звичайним редактором і інструментами для програмування без додаткових налаштувань для ігнорування таких помилок.