如何更新 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 类型的问题,但我只是没有在文件中看到它。

58603 次浏览

你可以试试这个:

obj.__dict__.update(my_data_dict)

干扰 __dict__是很有诱惑力的,但这不适用于从父类继承的属性。

您可以迭代 dict 以分配给对象:

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

或者你可以直接从查询集中修改它(确保你的查询集只返回你感兴趣的对象) :

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

这似乎是一件很自然的事情,你会想做但像你一样,我也没有在文件中找到它。文档确实说过,您应该在模型上创建 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()

我得到主键的名称,使用它与 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)

这允许我更新任何主键的实例。

使用 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)