Как обновить несколько полей экземпляра модели 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, но я просто не видел его в документах.
Ответы
Ответ 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)