2009-10-16 89 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__一塌糊涂,但不适用于从父类继承的属性。

您可以遍历分配给对象的字典:

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

或者你也可以直接从一个QuerySet修改(确保你的查询只设置返回你感兴趣的对象):

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

这是否与m2m领域的工作? – 2016-05-04 23:10:15

24

你可以试试这个:

obj.__dict__.update(my_data_dict) 
+6

这将不适用于继承属性。 – 2012-05-21 12:31:56

+1

它不适用于继承属性的含义是什么? – 2014-04-26 10:59:16

+0

另外,你是否试图更新一个ForeignKey,使用__dict__,相关的值名称是'field_name_id'而不是'field_name',你需要小心。 – levi 2015-10-01 07:00:36

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模型保存方法 - 正常和字典)与上面的身体上次下次我需要这个装饰的装饰器。我查了一下我用来做这件事的代码,除了我在保存之外这么做以外,其他都是一样的。有一个方法update_model_obj_from_dict(model_object,update_dict)与上面几乎相同的主体,并且预计我会选择何时调用save()。我有点喜欢有选择。所以也许在模型上的一个方法称为“set_from_dict”,除了最后一行以外的所有内容,以及稍后使用save。 – Purrell 2012-03-23 20:43:52

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 2017-03-13 09:36:21

相关问题