12 KiB
Тело запроса
Когда вам необходимо отправить данные из клиента (например, браузера) в ваш API, вы отправляете их как тело запроса.
Тело запроса — это данные, отправляемые клиентом в ваш API. Тело ответа — это данные, которые ваш API отправляет клиенту.
Ваш API почти всегда должен отправлять тело ответа. Но клиентам не обязательно всегда отправлять тело запроса: иногда они запрашивают только путь, возможно с некоторыми параметрами запроса, но без тела.
Чтобы объявить тело запроса, используйте модели Pydantic, со всей их мощью и преимуществами.
/// info | Информация
Чтобы отправить данные, используйте один из методов: POST
(чаще всего), PUT
, DELETE
или PATCH
.
Отправка тела с запросом GET
имеет неопределённое поведение в спецификациях, тем не менее это поддерживается FastAPI, но только для очень сложных/крайних случаев использования.
Поскольку это не рекомендуется, интерактивная документация со Swagger UI не будет отображать информацию для тела при использовании GET
, а промежуточные прокси-серверы могут не поддерживать такой вариант запроса.
///
Импортируйте BaseModel
из Pydantic
Первое, что нужно сделать, — импортировать BaseModel
из пакета pydantic
:
{* ../../docs_src/body/tutorial001_py310.py hl[2] *}
Создайте модель данных
Затем опишите свою модель данных как класс, наследующийся от BaseModel
.
Используйте стандартные типы Python для всех атрибутов:
{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *}
Так же, как при объявлении параметров запроса: когда атрибут модели имеет значение по умолчанию, он не обязателен. Иначе он обязателен. Используйте None
, чтобы сделать его просто необязательным.
Например, модель выше описывает такой JSON "объект" (или Python dict
):
{
"name": "Foo",
"description": "An optional description",
"price": 45.2,
"tax": 3.5
}
...так как description
и tax
являются необязательными (со значением по умолчанию None
), такой JSON "объект" тоже будет корректным:
{
"name": "Foo",
"price": 45.2
}
Объявите её как параметр
Чтобы добавить её в вашу операцию пути, объявите её так же, как вы объявляли параметры пути и параметры запроса:
{* ../../docs_src/body/tutorial001_py310.py hl[16] *}
...и укажите тип параметра как созданную вами модель, Item
.
Результаты
Всего лишь с этой аннотацией типов Python FastAPI:
- Считает тело запроса как JSON.
- Приведёт данные к соответствующим типам (если потребуется).
- Проведёт валидацию данных.
- Если данные некорректны, вернёт понятную и наглядную ошибку, указывающую, где именно и что было некорректно.
- Передаст полученные данные в параметр
item
.- Поскольку внутри функции вы объявили его с типом
Item
, у вас будет поддержка со стороны редактора кода (автозавершение и т. п.) для всех атрибутов и их типов.
- Поскольку внутри функции вы объявили его с типом
- Сгенерирует определения JSON Schema для вашей модели; вы можете использовать их и в других местах, если это имеет смысл для вашего проекта.
- Эти схемы будут частью сгенерированной схемы OpenAPI и будут использоваться автоматической документацией UIs.
Автоматическая документация
JSON Schema ваших моделей будет частью сгенерированной схемы OpenAPI и будет отображаться в интерактивной документации API:

А также они будут использоваться в документации API внутри каждой операции пути, где это требуется:

Поддержка редактора кода
В вашем редакторе кода внутри функции вы получите подсказки по типам и автозавершение повсюду (этого бы не было, если бы вы получали dict
вместо модели Pydantic):

Также вы получите проверку ошибок при некорректных операциях с типами:

Это не случайность — весь фреймворк построен вокруг такого дизайна.
И это было тщательно протестировано ещё на этапе проектирования, до реализации, чтобы убедиться, что всё будет работать со всеми редакторами.
В сам Pydantic даже были внесены некоторые изменения для поддержки этого.
Предыдущие скриншоты сделаны в Visual Studio Code.
Но вы получите такую же поддержку редактора кода в PyCharm и большинстве других редакторов Python:

/// tip | Совет
Если вы используете PyCharm в качестве редактора кода, вы можете использовать плагин Pydantic PyCharm Plugin.
Он улучшает поддержку моделей Pydantic в редакторе кода, включая:
- автозавершение
- проверки типов
- рефакторинг
- поиск
- инспекции
///
Использование модели
Внутри функции вам доступны все атрибуты объекта модели напрямую:
{* ../../docs_src/body/tutorial002_py310.py *}
/// info | Информация
В Pydantic v1 метод назывался .dict()
, в Pydantic v2 он был помечен как устаревший (но всё ещё поддерживается) и переименован в .model_dump()
.
Примеры здесь используют .dict()
для совместимости с Pydantic v1, но если вы можете использовать Pydantic v2, используйте .model_dump()
.
///
Тело запроса + параметры пути
Вы можете одновременно объявить параметры пути и тело запроса.
FastAPI распознает, что параметры функции, соответствующие параметрам пути, должны быть получены из пути, а параметры функции, объявленные как модели Pydantic, должны быть получены из тела запроса.
{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *}
Тело запроса + параметры пути + параметры запроса
Вы также можете одновременно объявить параметры тела, пути и запроса.
FastAPI распознает каждый из них и возьмёт данные из правильного источника.
{* ../../docs_src/body/tutorial004_py310.py hl[16] *}
Параметры функции будут распознаны следующим образом:
- Если параметр также объявлен в пути, он будет использоваться как параметр пути.
- Если параметр имеет скалярный тип (например,
int
,float
,str
,bool
и т. п.), он будет интерпретирован как параметр запроса. - Если параметр объявлен как тип модели Pydantic, он будет интерпретирован как тело запроса.
/// note | Заметка
FastAPI понимает, что значение q
не является обязательным из-за значения по умолчанию = None
.
Аннотации типов str | None
(Python 3.10+) или Union[str, None]
(Python 3.8+) не используются FastAPI для определения обязательности; он узнает, что параметр не обязателен, потому что у него есть значение по умолчанию = None
.
Но добавление аннотаций типов позволит вашему редактору кода лучше вас поддерживать и обнаруживать ошибки.
///
Без Pydantic
Если вы не хотите использовать модели Pydantic, вы также можете использовать параметры Body. См. раздел документации Тело — Несколько параметров: Единичные значения в теле{.internal-link target=_blank}.