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

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

Мне интересно, что такое стандартный способ обновления нескольких полей экземпляра модели в django?... Если у меня есть модель с некоторыми полями,

Class foomodel(models.Model):
    field1 = models.CharField(max_length=10)
    field2 = models.CharField(max_length=10)
    field3 = models.CharField(max_length=10)
    ...

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

Другими словами, скажем, у меня есть словарь с некоторыми данными в нем, в котором есть все, что я хочу записать в экземпляр этой модели. Экземпляр модели был создан на отдельном шаге, и пусть он еще не сохранился. Я могу сказать foo_instance.field1 = my_data_dict['field1'] для каждого поля, но что-то говорит мне, что должен быть способ вызова метода в экземпляре модели, где я просто передаю все пары значений поля одновременно и обновляет их. Что-то вроде foo_instance.update(my_data_dict). Я не вижу таких встроенных методов, как я, я пропустил это или как это эффективно сделано?

У меня такое ощущение, что это очевидный вопрос RTM, но я просто не видел его в документах.

4b9b3361

Ответ 1

Заманчиво возиться с __dict__, но это не относится к атрибутам, унаследованным от родительского класса.

Вы можете либо выполнить итерацию по dict для назначения объекту:

for (key, value) in my_data_dict.items():
    setattr(obj, key, value)

Или вы можете напрямую изменить его из набора запросов (убедитесь, что ваш набор запросов возвращает объект, который вас интересует):

FooModel.objects.filter(whatever="anything").update(**my_data_dict)

Ответ 2

Вы можете попробовать следующее:

obj.__dict__.update(my_data_dict)

Ответ 3

Кажется, что такая естественная вещь, которую вы хотели бы сделать, но, как и вы, я тоже не нашел ее в документах. Документы говорят, что вы должны использовать подкласс класса save() для модели. И это то, что я делаю.

def save(self, **kwargs):
    mfields = iter(self._meta.fields)
    mods = [(f.attname, kwargs[f.attname]) for f in mfields if f.attname in kwargs]
    for fname, fval in mods: setattr(self, fname, fval)
    super(MyModel, self).save()

Ответ 4

Я получаю имя первичного ключа, использую его для фильтрации с помощью Queryset.filter() и обновляю с помощью Queryset.update().

fooinstance = ...    
# Find primary key and make a dict for filter
pk_name foomodel._meta.pk.name
filtr = {pk_name: getattr(fooinstance, pk_name)}
# Create a dict attribute to update
updat = {'name': 'foo', 'lastname': 'bar'}
# Apply
foomodel.objects.filter(**filtr).update(**updat)

Это позволяет мне обновить экземпляр независимо от первичного ключа.

Ответ 5

Обновление с помощью update()

Discussion.objects.filter(slug=d.slug)
    .update(title=form_data['title'],
            category=get_object_or_404(Category, pk=form_data['category']),
            description=form_data['description'], closed=True)