我可以使用
Model(**dictionary)
创建一个新的 django 模型对象,但是如果我想以相同的方式更新实例,我发现只有 update_or_create
有问题并且经常返回“重复 PK”错误。在模型对象上调用自定义辅助函数似乎也不是特别Pythonic。或者,您可以使用此模式:
Model.objects.get(id=id).update(**dict)
或
model.__dict__.update(**dict)
model.save()
后者感觉就像是黑客攻击,我读过几次,它不“应该”这样做。第一种方法需要查询调用,并且再次感觉不正确,因为模型实例可能已经实例化并且要更新它,我们需要再次向数据库发送查询?
我还读到“您可以使用表单来完成此操作” - 但并不总是用户在数据库中更新模型,我们可能会编写需要更新模型的各种函数。我想知道以下代码无法实现/是否有原因?模型对象不能以这种方式直接调用和更新是否有原因?
model_instance(**dict)
model_instance.save()
模型实例[Django 文档]没有任何通过输入关键字参数来更新字段值的内置方法。
update()
以下查询将立即更新数据库行,但缺点是它不会调用任何您可能已注册到模型的预保存或后保存信号[Django文档]:
Model.objects.filter(id=model_instance.id).update(**dict_)
正如您所提到的,如果您打算继续使用同一实例,则需要从数据库更新其值:
model_instance.refresh_from_db()
model_instance(**dict_)
不起作用Django 模型实例(对象)不可调用。默认情况下,对象不能像函数一样被调用。例如,当您创建一个普通字典
dict_ = dict()
时,您无法通过调用dict_(**kwargs)
来更新它。通过覆盖 __call__
[Python 文档]类方法,可以使对象变得可调用。
update()
方法您可以创建自己的模型方法,这样您只需进行一次数据库调用(并保留信号)。例如,您可以创建一个 抽象基类 [Django 文档],您的所有模型都继承自(而不是从
models.Model
),例如
class ModelWithUpdate(models.Model):
class Meta:
abstract = True
def update(self, commit=False, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
if commit:
self.save()
然后你的用法是:
model_instance.update(**dict_)
model_instance.save()
# or a shortcut
model_instance.update(commit=True, **dict_)
只是:
Model.objects.filter(id=id).update(**kwargs)
更新方法如下:
def update(self, **kwargs):
return type(self).objects.filter(pk=self.pk).update(**kwargs)
也可以做到这一点。