# Body - Обновления { #body-updates }

## Обновление с заменой при помощи `PUT` { #update-replacing-with-put }

Для полного обновления элемента можно воспользоваться операцией <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT" class="external-link" target="_blank">HTTP `PUT`</a>.

Вы можете использовать `jsonable_encoder`, чтобы преобразовать входные данные в данные, которые можно сохранить как JSON (например, в NoSQL-базе данных). Например, преобразование `datetime` в `str`.

{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *}

`PUT` используется для получения данных, которые должны полностью заменить существующие данные.

### Предупреждение о замене { #warning-about-replacing }

Это означает, что если вы хотите обновить элемент `bar`, используя `PUT` с телом, содержащим:

```Python
{
    "name": "Barz",
    "price": 3,
    "description": None,
}
```

поскольку оно не включает уже сохраненный атрибут `"tax": 20.2`, входная модель примет значение по умолчанию `"tax": 10.5`.

И данные будут сохранены с этим "новым" `tax`, равным `10,5`.

## Частичное обновление с помощью `PATCH` { #partial-updates-with-patch }

Также можно использовать <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH" class="external-link" target="_blank">HTTP `PATCH`</a> операцию для *частичного* обновления данных.

Это означает, что можно передавать только те данные, которые необходимо обновить, оставляя остальные нетронутыми.

/// note | Технические детали

`PATCH` менее распространен и известен, чем `PUT`.

А многие команды используют только `PUT`, даже для частичного обновления.

Вы можете **свободно** использовать их как угодно, **FastAPI** не накладывает никаких ограничений.

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

///

### Использование параметра `exclude_unset` в Pydantic { #using-pydantics-exclude-unset-parameter }

Если необходимо выполнить частичное обновление, то очень полезно использовать параметр `exclude_unset` в методе `.model_dump()` модели Pydantic.

Например, `item.model_dump(exclude_unset=True)`.

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

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

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

///

В результате будет сгенерирован словарь, содержащий только те данные, которые были заданы при создании модели `item`, без учета значений по умолчанию. Затем вы можете использовать это для создания словаря только с теми данными, которые были установлены (отправлены в запросе), опуская значения по умолчанию:

{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *}

### Использование параметра `update` в Pydantic { #using-pydantics-update-parameter }

Теперь можно создать копию существующей модели, используя `.model_copy()`, и передать параметр `update` с `dict`, содержащим данные для обновления.

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

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

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

///

Например, `stored_item_model.model_copy(update=update_data)`:

{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *}

### Кратко о частичном обновлении { #partial-updates-recap }

В целом, для применения частичных обновлений необходимо:

* (Опционально) использовать `PATCH` вместо `PUT`.
* Извлечь сохранённые данные.
* Поместить эти данные в Pydantic модель.
* Сгенерировать `dict` без значений по умолчанию из входной модели (с использованием `exclude_unset`).
    * Таким образом, можно обновлять только те значения, которые действительно установлены пользователем, вместо того чтобы переопределять значения, уже сохраненные в модели по умолчанию.
* Создать копию хранимой модели, обновив ее атрибуты полученными частичными обновлениями (с помощью параметра `update`).
* Преобразовать скопированную модель в то, что может быть сохранено в вашей БД (например, с помощью `jsonable_encoder`).
    * Это сравнимо с повторным использованием метода модели `.model_dump()`, но при этом происходит проверка (и преобразование) значений в типы данных, которые могут быть преобразованы в JSON, например, `datetime` в `str`.
* Сохранить данные в своей БД.
* Вернуть обновленную модель.

{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *}

/// tip | Подсказка

Эту же технику можно использовать и для операции HTTP `PUT`.

Но в приведенном примере используется `PATCH`, поскольку он был создан именно для таких случаев использования.

///

/// note | Технические детали

Обратите внимание, что входная модель по-прежнему валидируется.

Таким образом, если вы хотите получать частичные обновления, в которых могут быть опущены все атрибуты, вам необходимо иметь модель, в которой все атрибуты помечены как необязательные (со значениями по умолчанию или `None`).

Чтобы отличить модели со всеми необязательными значениями для **обновления** от моделей с обязательными значениями для **создания**, можно воспользоваться идеями, описанными в [Дополнительные модели](extra-models.md){.internal-link target=_blank}.

///
