7.1 KiB
Body - Обновления
Полное обновление с помощью PUT
Для полного обновления элемента можно воспользоваться операцией HTTP PUT
.
Вы можете использовать функцию jsonable_encoder
для преобразования входных данных в JSON, так как нередки случаи, когда работать можно только с простыми типами данных (например, для хранения в NoSQL-базе данных).
{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *}
PUT
используется для получения данных, которые должны полностью заменить существующие данные.
Предупреждение о замене
Это означает, что если вы хотите обновить элемент bar
, используя PUT
с телом, содержащим:
{
"name": "Barz",
"price": 3,
"description": None,
}
поскольку оно не включает уже сохраненный атрибут "tax": 20.2
, входная модель примет значение по умолчанию "tax": 10.5
.
И данные будут сохранены с этим "новым" tax
, равным 10,5
.
Частичное обновление с помощью PATCH
Также можно использовать HTTP PATCH
операцию для частичного обновления данных.
Это означает, что можно передавать только те данные, которые необходимо обновить, оставляя остальные нетронутыми.
/// note | Технические детали
PATCH
менее распространен и известен, чем PUT
.
А многие команды используют только PUT
, даже для частичного обновления.
Вы можете свободно использовать их как угодно, FastAPI не накладывает никаких ограничений.
Но в данном руководстве более или менее понятно, как они должны использоваться.
///
Использование параметра exclude_unset
в Pydantic
Если необходимо выполнить частичное обновление, то очень полезно использовать параметр exclude_unset
в методе .dict()
модели Pydantic.
Например, item.dict(exclude_unset=True)
.
В результате будет сгенерирован словарь, содержащий только те данные, которые были заданы при создании модели item
, без учета значений по умолчанию. Затем вы можете использовать это для создания словаря только с теми данными, которые были установлены (отправлены в запросе), опуская значения по умолчанию:
{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *}
Использование параметра update
в Pydantic
Теперь можно создать копию существующей модели, используя .copy()
, и передать параметр update
с dict
, содержащим данные для обновления.
Например, stored_item_model.copy(update=update_data)
:
{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *}
Кратко о частичном обновлении
В целом, для применения частичных обновлений необходимо:
- (Опционально) использовать
PATCH
вместоPUT
. - Извлечь сохранённые данные.
- Поместить эти данные в Pydantic модель.
- Сгенерировать
dict
без значений по умолчанию из входной модели (с использованиемexclude_unset
).- Таким образом, можно обновлять только те значения, которые действительно установлены пользователем, вместо того чтобы переопределять значения, уже сохраненные в модели по умолчанию.
- Создать копию хранимой модели, обновив ее атрибуты полученными частичными обновлениями (с помощью параметра
update
). - Преобразовать скопированную модель в то, что может быть сохранено в вашей БД (например, с помощью
jsonable_encoder
).- Это сравнимо с повторным использованием метода модели
.dict()
, но при этом происходит проверка (и преобразование) значений в типы данных, которые могут быть преобразованы в JSON, например,datetime
вstr
.
- Это сравнимо с повторным использованием метода модели
- Сохранить данные в своей БД.
- Вернуть обновленную модель.
{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *}
/// tip | Подсказка
Эту же технику можно использовать и для операции HTTP PUT
.
Но в приведенном примере используется PATCH
, поскольку он был создан именно для таких случаев использования.
///
/// note | Технические детали
Обратите внимание, что входная модель по-прежнему валидируется.
Таким образом, если вы хотите получать частичные обновления, в которых могут быть опущены все атрибуты, вам необходимо иметь модель, в которой все атрибуты помечены как необязательные (со значениями по умолчанию или None
).
Чтобы отличить модели со всеми необязательными значениями для обновления от моделей с обязательными значениями для создания, можно воспользоваться идеями, описанными в Дополнительные модели{.internal-link target=_blank}.
///