在Django中使用QuerySet.update()与ModelInstance.save()

时间:2010-12-23 13:52:50

标签: django

我很好奇其他人对这个问题的看法......

过去几天我一直在来回使用QuerySet.update()ModelInstance.save()。显然,如果有很多字段被更改,我会使用save(),但是为了更新几个字段,我认为最好使用QuerySet.update()。使用QuerySet.update()的好处是,您可以在同一对象的不同字段上同时运行多个线程update(),并且您不会遇到种族问题。默认的save()方法会保存所有字段,因此来自两个线程的并行save()会出现问题。

那么问题就是如果你有重载的自定义save()方法。我能想到的最好的方法是将自定义save()方法中的任何内容抽象为单独的更新程序方法,这些方法实际上使用QuerySet.update()来设置模型中的几个字段。有人用过这种模式吗?

令人恼火的是,在Django Admin中,即使在您只编辑一个字段的更改列表模式下进行编辑,整个模型也会保存。这基本上意味着如果有人在他/她的浏览器上打开了更改列表,而在系统中某个其他地方更新了某个字段,则当该用户从更改列表中保存更改时,该更新的值将被丢弃。这个问题有解决方案吗?

思想?

感谢。

2 个答案:

答案 0 :(得分:8)

使用QuerySet.update()的主要原因是您可以只使用一个数据库查询来更新多个对象,而对对象的save方法的每次调用都会到达数据库!

值得一提的另一点是,django的pre_save& post_save信号仅在您调用对象的save - 方法时发送,而不是在QuerySet.update()上发送。

针对您描述的冲突问题,我认为如果您点击“保存”然后您必须发现之后某些值与更改它们时相同,但是您保持不变的某些值改变了吗?!?当然,您可以将管理员的save_model或对象的save方法修改为您建议的行为。

答案 1 :(得分:3)

您描述的关于Django Admin的问题主要是使用过时的副本更新模型实例。通过向每个模型实例添加版本号并在每次更新时增加数量,可以轻松修复。然后在模型的save方法中,确保您保存的内容不在数据库中已有的内容之后。

  

我想确保当对同一个对象进行并行写入时,每次写入都会更新不同的字段,但它们不会覆盖彼此的值。

根据应用,这可能是也可能不是明智之举。即使只更新一个字段,保存整个模型通常可以避免破坏数据的完整性。关于以下三足飞行旅游行程示例的思考。假设有三个字段的实例代表三条腿,三个字段是SF->LALA->DCDC->NY。现在,如果有一个更新是将前两个分支更新为SF->SDSD->DC,则另一个更新是将最后两个分支更新为LA->SJSJ->NY,如果您允许update而不是保存完整的模型实例,你会发现SF->SDLA->SJSJ->NY的行程中断。