# Тело запроса { #request-body }

Когда вам необходимо отправить данные из клиента (например, браузера) в ваш API, вы отправляете их как **тело запроса**.

Тело **запроса** — это данные, отправляемые клиентом в ваш API. Тело **ответа** — это данные, которые ваш API отправляет клиенту.

Ваш API почти всегда должен отправлять тело **ответа**. Но клиентам не обязательно всегда отправлять **тело запроса**: иногда они запрашивают только путь, возможно с некоторыми параметрами запроса, но без тела.

Чтобы объявить тело **запроса**, используйте модели <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>, со всей их мощью и преимуществами.

/// info | Информация

Чтобы отправить данные, используйте один из методов: `POST` (чаще всего), `PUT`, `DELETE` или `PATCH`.

Отправка тела с запросом `GET` имеет неопределённое поведение в спецификациях, тем не менее это поддерживается FastAPI, но только для очень сложных/крайних случаев использования.

Поскольку это не рекомендуется, интерактивная документация со Swagger UI не будет отображать информацию для тела при использовании `GET`, а промежуточные прокси-серверы могут не поддерживать такой вариант запроса.

///

## Импортируйте `BaseModel` из Pydantic { #import-pydantics-basemodel }

Первое, что нужно сделать, — импортировать `BaseModel` из пакета `pydantic`:

{* ../../docs_src/body/tutorial001_py310.py hl[2] *}

## Создайте модель данных { #create-your-data-model }

Затем опишите свою модель данных как класс, наследующийся от `BaseModel`.

Используйте стандартные типы Python для всех атрибутов:

{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *}

Так же, как при объявлении параметров запроса: когда атрибут модели имеет значение по умолчанию, он не обязателен. Иначе он обязателен. Используйте `None`, чтобы сделать его просто необязательным.

Например, модель выше описывает такой JSON "объект" (или Python `dict`):

```JSON
{
    "name": "Foo",
    "description": "An optional description",
    "price": 45.2,
    "tax": 3.5
}
```

...так как `description` и `tax` являются необязательными (со значением по умолчанию `None`), такой JSON "объект" тоже будет корректным:

```JSON
{
    "name": "Foo",
    "price": 45.2
}
```

## Объявите её как параметр { #declare-it-as-a-parameter }

Чтобы добавить её в вашу *операцию пути*, объявите её так же, как вы объявляли параметры пути и параметры запроса:

{* ../../docs_src/body/tutorial001_py310.py hl[16] *}

...и укажите тип параметра как созданную вами модель, `Item`.

## Результаты { #results }

Всего лишь с этой аннотацией типов Python **FastAPI**:

* Считает тело запроса как JSON.
* Приведёт данные к соответствующим типам (если потребуется).
* Проведёт валидацию данных.
    * Если данные некорректны, вернёт понятную и наглядную ошибку, указывающую, где именно и что было некорректно.
* Передаст полученные данные в параметр `item`.
    * Поскольку внутри функции вы объявили его с типом `Item`, у вас будет поддержка со стороны редактора кода (автозавершение и т. п.) для всех атрибутов и их типов.
* Сгенерирует определения <a href="https://json-schema.org" class="external-link" target="_blank">JSON Schema</a> для вашей модели; вы можете использовать их и в других местах, если это имеет смысл для вашего проекта.
* Эти схемы будут частью сгенерированной схемы OpenAPI и будут использоваться автоматической документацией <abbr title="User Interfaces – Пользовательские интерфейсы">UIs</abbr>.

## Автоматическая документация { #automatic-docs }

JSON Schema ваших моделей будет частью сгенерированной схемы OpenAPI и будет отображаться в интерактивной документации API:

<img src="/img/tutorial/body/image01.png">

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

<img src="/img/tutorial/body/image02.png">

## Поддержка редактора кода { #editor-support }

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

<img src="/img/tutorial/body/image03.png">

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

<img src="/img/tutorial/body/image04.png">

Это не случайность — весь фреймворк построен вокруг такого дизайна.

И это было тщательно протестировано ещё на этапе проектирования, до реализации, чтобы убедиться, что всё будет работать со всеми редакторами.

В сам Pydantic даже были внесены некоторые изменения для поддержки этого.

Предыдущие скриншоты сделаны в <a href="https://code.visualstudio.com" class="external-link" target="_blank">Visual Studio Code</a>.

Но вы получите такую же поддержку редактора кода в <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> и большинстве других редакторов Python:

<img src="/img/tutorial/body/image05.png">

/// tip | Совет

Если вы используете <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> в качестве редактора кода, вы можете использовать плагин <a href="https://github.com/koxudaxi/pydantic-pycharm-plugin/" class="external-link" target="_blank">Pydantic PyCharm Plugin</a>.

Он улучшает поддержку моделей Pydantic в редакторе кода, включая:

* автозавершение
* проверки типов
* рефакторинг
* поиск
* инспекции

///

## Использование модели { #use-the-model }

Внутри функции вам доступны все атрибуты объекта модели напрямую:

{* ../../docs_src/body/tutorial002_py310.py *}

/// info | Информация

В Pydantic v1 метод назывался `.dict()`, в Pydantic v2 он был помечен как устаревший (но всё ещё поддерживается) и переименован в `.model_dump()`.

Примеры здесь используют `.dict()` для совместимости с Pydantic v1, но если вы можете использовать Pydantic v2, используйте `.model_dump()`.

///

## Тело запроса + параметры пути { #request-body-path-parameters }

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

**FastAPI** распознает, что параметры функции, соответствующие параметрам пути, должны быть **получены из пути**, а параметры функции, объявленные как модели Pydantic, должны быть **получены из тела запроса**.

{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *}

## Тело запроса + параметры пути + параметры запроса { #request-body-path-query-parameters }

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

**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.9+) не используются FastAPI для определения обязательности; он узнает, что параметр не обязателен, потому что у него есть значение по умолчанию `= None`.

Но добавление аннотаций типов позволит вашему редактору кода лучше вас поддерживать и обнаруживать ошибки.

///

## Без Pydantic { #without-pydantic }

Если вы не хотите использовать модели Pydantic, вы также можете использовать параметры **Body**. См. раздел документации [Тело — Несколько параметров: Единичные значения в теле](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.
