Подтвердить что ты не робот

Как использовать словарь для обновления полей в моделях Django?

Предположим, что у меня есть такая модель:

class Book(models.Model):
    num_pages = ...
    author = ...
    date = ...

Могу ли я создать словарь, а затем вставить или обновить модель, используя его?

d = {"num_pages":40, author:"Jack", date:"3324"}
4b9b3361

Ответ 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()

Ответ 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 - это то, что существует ограниченный и проверенный набор полей, что не относится к ручному обновлению.