Так же, как с помощью Query вы можете добавлять валидацию и метаданные для query-параметров, так и с помощью Path вы можете добавлять такую же валидацию и метаданные для path-параметров.
Сначала импортируйте Path из fastapi, а также импортируйте Annotated:
fromtypingimportAnnotatedfromfastapiimportFastAPI,Path,Queryapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_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}ifq:results.update({"q":q})returnresults
fromtypingimportAnnotated,UnionfromfastapiimportFastAPI,Path,Queryapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_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}ifq:results.update({"q":q})returnresults
fromtypingimportUnionfromfastapiimportFastAPI,Path,Queryfromtyping_extensionsimportAnnotatedapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_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}ifq:results.update({"q":q})returnresults
Подсказка
Рекомендуется использовать версию с Annotated если возможно.
fromfastapiimportFastAPI,Path,Queryapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_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}ifq:results.update({"q":q})returnresults
Подсказка
Рекомендуется использовать версию с Annotated если возможно.
fromtypingimportUnionfromfastapiimportFastAPI,Path,Queryapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_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}ifq:results.update({"q":q})returnresults
Информация
Поддержка Annotated была добавлена в FastAPI начиная с версии 0.95.0 (и с этой версии рекомендуется использовать этот подход).
Если вы используете более старую версию, вы столкнётесь с ошибками при попытке использовать Annotated.
Убедитесь, что вы обновили версию FastAPI как минимум до 0.95.1 перед тем, как использовать Annotated.
Вы можете указать все те же параметры, что и для Query.
Например, чтобы указать значение метаданных title для path-параметра item_id, вы можете написать:
fromtypingimportAnnotatedfromfastapiimportFastAPI,Path,Queryapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_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}ifq:results.update({"q":q})returnresults
fromtypingimportAnnotated,UnionfromfastapiimportFastAPI,Path,Queryapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_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}ifq:results.update({"q":q})returnresults
fromtypingimportUnionfromfastapiimportFastAPI,Path,Queryfromtyping_extensionsimportAnnotatedapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_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}ifq:results.update({"q":q})returnresults
Подсказка
Рекомендуется использовать версию с Annotated если возможно.
fromfastapiimportFastAPI,Path,Queryapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_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}ifq:results.update({"q":q})returnresults
Подсказка
Рекомендуется использовать версию с Annotated если возможно.
fromtypingimportUnionfromfastapiimportFastAPI,Path,Queryapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_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}ifq:results.update({"q":q})returnresults
Примечание
Path-параметр всегда является обязательным, поскольку он составляет часть пути.
Поэтому следует объявить его с помощью ..., чтобы обозначить, что этот параметр обязательный.
Тем не менее, даже если вы объявите его как None или установите для него значение по умолчанию, это ни на что не повлияет и параметр останется обязательным.
Это не имеет большого значения, если вы используете Annotated.
Допустим, вы хотите объявить query-параметр q как обязательный параметр типа str.
И если вам больше ничего не нужно указывать для этого параметра, то нет необходимости использовать Query.
Но вам по-прежнему нужно использовать Path для path-параметра item_id. И если по какой-либо причине вы не хотите использовать Annotated, то могут возникнуть небольшие сложности.
Если вы поместите параметр со значением по умолчанию перед другим параметром, у которого нет значения по умолчанию, то Python укажет на ошибку.
Но вы можете изменить порядок параметров, чтобы параметр без значения по умолчанию (query-параметр q) шёл первым.
Это не имеет значения для FastAPI. Он распознает параметры по их названиям, типам и значениям по умолчанию (Query, Path, и т.д.), ему не важен их порядок.
Поэтому вы можете определить функцию так:
Подсказка
Рекомендуется использовать версию с Annotated если возможно.
fromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(q:str,item_id:int=Path(title="The ID of the item to get")):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
Но имейте в виду, что если вы используете Annotated, вы не столкнётесь с этой проблемой, так как вы не используете Query() или Path() в качестве значения по умолчанию для параметра функции.
fromtypingimportAnnotatedfromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(q:str,item_id:Annotated[int,Path(title="The ID of the item to get")]):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
fromfastapiimportFastAPI,Pathfromtyping_extensionsimportAnnotatedapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(q:str,item_id:Annotated[int,Path(title="The ID of the item to get")]):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
Задайте нужный вам порядок параметров, полезные приёмы¶
Подсказка
Это не имеет большого значения, если вы используете Annotated.
Здесь описан небольшой приём, который может оказаться удобным, хотя часто он вам не понадобится.
Если вы хотите:
объявить query-параметр q без Query и без значения по умолчанию
объявить path-параметр item_id с помощью Path
указать их в другом порядке
не использовать Annotated
...то вы можете использовать специальную возможность синтаксиса Python.
Передайте * в качестве первого параметра функции.
Python не будет ничего делать с *, но он будет знать, что все следующие параметры являются именованными аргументами (парами ключ-значение), также известными как kwargs, даже если у них нет значений по умолчанию.
fromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(*,item_id:int=Path(title="The ID of the item to get"),q:str):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
Имейте в виду, что если вы используете Annotated, то, поскольку вы не используете значений по умолчанию для параметров функции, то у вас не возникнет подобной проблемы и вам не придётся использовать *.
fromtypingimportAnnotatedfromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(item_id:Annotated[int,Path(title="The ID of the item to get")],q:str):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
fromfastapiimportFastAPI,Pathfromtyping_extensionsimportAnnotatedapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(item_id:Annotated[int,Path(title="The ID of the item to get")],q:str):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
С помощью Query и Path (и других классов, которые мы разберём позже) вы можете добавлять ограничения для числовых данных.
В этом примере при указании ge=1, параметр item_id должен быть больше или равен 1 ("greater than or equal").
fromtypingimportAnnotatedfromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(item_id:Annotated[int,Path(title="The ID of the item to get",ge=1)],q:str):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
fromfastapiimportFastAPI,Pathfromtyping_extensionsimportAnnotatedapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(item_id:Annotated[int,Path(title="The ID of the item to get",ge=1)],q:str):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
Подсказка
Рекомендуется использовать версию с Annotated если возможно.
fromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(*,item_id:int=Path(title="The ID of the item to get",ge=1),q:str):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
Валидация числовых данных: больше и меньше или равно¶
То же самое применимо к:
gt: больше (greater than)
le: меньше или равно (less than or equal)
fromtypingimportAnnotatedfromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_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}ifq:results.update({"q":q})returnresults
fromfastapiimportFastAPI,Pathfromtyping_extensionsimportAnnotatedapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_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}ifq:results.update({"q":q})returnresults
Подсказка
Рекомендуется использовать версию с Annotated если возможно.
fromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(*,item_id:int=Path(title="The ID of the item to get",gt=0,le=1000),q:str,):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
Валидация числовых данных: числа с плавающей точкой, больше и меньше¶
Валидация также применима к значениям типа float.
В этом случае становится важной возможность добавить ограничение gt, вместо ge, поскольку в таком случае вы можете, например, создать ограничение, чтобы значение было больше 0, даже если оно меньше 1.
Таким образом, 0.5 будет корректным значением. А 0.0 или 0 — нет.
То же самое справедливо и для lt.
fromtypingimportAnnotatedfromfastapiimportFastAPI,Path,Queryapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_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}ifq:results.update({"q":q})returnresults
fromfastapiimportFastAPI,Path,Queryfromtyping_extensionsimportAnnotatedapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_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}ifq:results.update({"q":q})returnresults
Подсказка
Рекомендуется использовать версию с Annotated если возможно.
fromfastapiimportFastAPI,Path,Queryapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_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}ifq:results.update({"q":q})returnresults
С помощью 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.
Использование функций (вместо использования классов напрямую) нужно для того, чтобы ваш редактор не подсвечивал ошибки, связанные с их типами.
Таким образом вы можете использовать привычный вам редактор и инструменты разработки, не добавляя дополнительных конфигураций для игнорирования подобных ошибок.