Как использовать словарь для обновления полей в моделях Django?
Предположим, что у меня есть такая модель:
class Book(models.Model):
num_pages = ...
author = ...
date = ...
Могу ли я создать словарь, а затем вставить или обновить модель, используя его?
d = {"num_pages":40, author:"Jack", date:"3324"}
Ответы
Ответ 1
Вот пример создания с использованием словаря d:
Book.objects.create(**d)
Чтобы обновить существующую модель, вам нужно будет использовать метод QuerySet filter
. Предполагая, что вы знаете pk
книги, которую хотите обновить:
Book.objects.filter(pk=pk).update(**d)
Ответ 2
Если вы знаете, что хотите его создать:
Book.objects.create(**d)
Предполагая, что вам нужно проверить существующий экземпляр, вы можете найти его с помощью get или create:
instance, created = Book.objects.get_or_create(slug=slug, defaults=d)
if not created:
for attr, value in d.iteritems():
setattr(instance, attr, value)
instance.save()
Как уже упоминалось в другом ответе, вы также можете использовать функцию update
в диспетчере запросов, но я считаю, что не будет отправлять какие-либо сигналы (что может не иметь значения для вас, если вы их не используете). Однако вы, вероятно, не должны использовать его для изменения одного объекта:
Book.objects.filter(id=id).update()
Ответ 3
Используйте **
для создания новой модели. Прокрутите словарь и используйте setattr()
для обновления существующей модели.
От Tom Christie Django Rest Framework
https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/serializers.py
for attr, value in validated_data.items():
setattr(instance, attr, value)
instance.save()
Ответ 4
Добавляя в дополнение к другим ответам, здесь немного более безопасная версия, чтобы предотвратить беспорядок со связанными полями:
def is_simple_editable_field(field):
return (
field.editable
and not field.primary_key
and not isinstance(field, (ForeignObjectRel, RelatedField))
)
def update_from_dict(instance, attrs, commit):
allowed_field_names = {
f.name for f in instance._meta.get_fields()
if is_simple_editable_field(f)
}
for attr, val in attrs.items():
if attr in allowed_field_names:
setattr(instance, attr, val)
if commit:
instance.save()
Он проверяет, что поле, которое вы пытаетесь обновить, редактируется, не является первичным ключом и не является одним из связанных полей.
Пример использования:
book = Book.objects.first()
update_from_dict(book, {"num_pages":40, author:"Jack", date:"3324"})
Роскошные сериализаторы DRF .create
и .update
- это то, что существует ограниченный и проверенный набор полей, что не относится к ручному обновлению.