2009-10-16 2 views
43

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

ответ

93

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

Вы можете перебирать в Dict, присваиваемый объект:

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

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

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

это работает с полями m2m? –

24

Вы можете попробовать это:

obj.__dict__.update(my_data_dict) 
+6

Это не относится к унаследованным атрибутам. –

+1

Каковы последствия того, что он не будет применяться к унаследованным атрибутам? –

+0

Кроме того, вы пытаетесь обновить ForeignKey, используя имя __dict__, связанные значения: 'field_name_id' не' field_name', вам нужно быть осторожным с этим. – levi

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() 
+1

Думая о создании декоратора для моделей, который добавляет новый метод «dict_save» (так что 2 метода сохранения для модели - нормальный и dict) с телом выше следующего раза, когда мне это нужно. Я искал код, который я использовал для этого, и это то же самое, за исключением того, что я делал это вне сохранения.Имел метод update_model_obj_from_dict (model_object, update_dict) практически с тем же телом, что и выше, и ожидал, что я выберу, когда вызывать save() после. Я вроде как выбор. так что, возможно, метод на модели под названием «set_from_dict» со всем выше, кроме последней строки, и просто с помощью сохранения позже. – Purrell

2

Я получаю имя первичного ключа, используйте его для фильтрации с 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) 

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

1

Обновление с помощью 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) 
+0

Добро пожаловать в SO. При отправке ответов укажите объяснение своего кода и не забудьте отформатировать текст. – Tony

Смежные вопросы