为什么不能像这样更新 django 模型实例:instance(**update_dict)?

phi*_*her 4 python django model

我可以创建一个新的 django 模型对象,Model(**dictionary)但如果我想以相同的方式更新一个实例,我发现只有update_or_create哪个有问题并且经常返回“重复 PK”错误。在模型对象上调用自定义辅助函数似乎也不是特别Pythonic。或者,您可以使用此模式:

 Model.objects.get(id=id).update(**dict)
Run Code Online (Sandbox Code Playgroud)

或者

model.__dict__.update(**dict)
model.save()
Run Code Online (Sandbox Code Playgroud)

后者感觉就像一个黑客,我读过几次,它不“应该”以这种方式完成。第一种方法需要查询调用,并且再次感觉不正确,因为模型实例可能已经实例化并且要更新它,我们需要再次向数据库发送查询?

我还读到“您可以使用表单来完成此操作” - 但并不总是用户在数据库中更新模型,我们可能会编写需要更新模型的各种函数。我想知道以下代码无法实现/是否有原因?模型对象不能以这种方式直接调用和更新是否有原因?

model_instance(**dict)
model_instance.save()
Run Code Online (Sandbox Code Playgroud)

ely*_*yas 11

模型实例[Django 文档]没有任何通过输入关键字参数来更新字段值的内置方法。

\n

查询集update()

\n

以下查询将立即更新数据库行,但缺点是它不会调用您可能已注册到模型的任何预保存或后保存信号 [Django 文档]:

\n
Model.objects.filter(id=model_instance.id).update(**dict_)\n
Run Code Online (Sandbox Code Playgroud)\n

正如您所提到的,如果您打算继续使用同一实例,则需要从数据库更新其值:

\n
model_instance.refresh_from_db()\n
Run Code Online (Sandbox Code Playgroud)\n

为什么model_instance(**dict_)不起作用

\n

Django 模型实例(对象)不可调用。默认情况下,对象不能像函数一样被调用。例如,当您创建一个普通的 dict 时dict_ = dict(),您无法通过调用 来更新它dict_(**kwargs)。可以通过重写[Python 文档]类方法来使对象可调用__call__

\n

模型上的解决方案 \xe2\x80\x93 自定义update()方法

\n

您可以创建自己的模型方法,这样您只需进行一次数据库调用(并保留信号)。例如,您可以创建一个抽象基类 [Django 文档],您的所有模型都继承自(而不是继承自models.Model),例如

\n
class ModelWithUpdate(models.Model):\n    class Meta:\n        abstract = True\n\n    def update(self, commit=False, **kwargs):\n        for key, value in kwargs.items():\n            setattr(self, key, value)\n        if commit:\n            self.save()\n
Run Code Online (Sandbox Code Playgroud)\n

然后你的用法是:

\n
model_instance.update(**dict_)\nmodel_instance.save()\n\n# or a shortcut\nmodel_instance.update(commit=True, **dict_)\n
Run Code Online (Sandbox Code Playgroud)\n