我很好奇其他人对这个问题的看法......
过去几天我一直在来回使用QuerySet.update()
与ModelInstance.save()
。显然,如果有很多字段被更改,我会使用save()
,但是为了更新几个字段,我认为最好使用QuerySet.update()
。使用QuerySet.update()
的好处是,您可以在同一对象的不同字段上同时运行多个线程update()
,并且您不会遇到种族问题。默认的save()
方法会保存所有字段,因此来自两个线程的并行save()
会出现问题。
那么问题就是如果你有重载的自定义save()
方法。我能想到的最好的方法是将自定义save()
方法中的任何内容抽象为单独的更新程序方法,这些方法实际上使用QuerySet.update()
来设置模型中的几个字段。有人用过这种模式吗?
令人恼火的是,在Django Admin中,即使在您只编辑一个字段的更改列表模式下进行编辑,整个模型也会保存。这基本上意味着如果有人在他/她的浏览器上打开了更改列表,而在系统中某个其他地方更新了某个字段,则当该用户从更改列表中保存更改时,该更新的值将被丢弃。这个问题有解决方案吗?
思想?
感谢。
答案 0 :(得分:8)
使用QuerySet.update()
的主要原因是您可以只使用一个数据库查询来更新多个对象,而对对象的save
方法的每次调用都会到达数据库!
值得一提的另一点是,django的pre_save
& post_save
信号仅在您调用对象的save
- 方法时发送,而不是在QuerySet.update()
上发送。
针对您描述的冲突问题,我认为如果您点击“保存”然后您必须发现之后某些值与更改它们时相同,但是您保持不变的某些值改变了吗?!?当然,您可以将管理员的save_model
或对象的save
方法修改为您建议的行为。
答案 1 :(得分:3)
您描述的关于Django Admin的问题主要是使用过时的副本更新模型实例。通过向每个模型实例添加版本号并在每次更新时增加数量,可以轻松修复。然后在模型的save
方法中,确保您保存的内容不在数据库中已有的内容之后。
我想确保当对同一个对象进行并行写入时,每次写入都会更新不同的字段,但它们不会覆盖彼此的值。
根据应用,这可能是也可能不是明智之举。即使只更新一个字段,保存整个模型通常可以避免破坏数据的完整性。关于以下三足飞行旅游行程示例的思考。假设有三个字段的实例代表三条腿,三个字段是SF->LA
,LA->DC
,DC->NY
。现在,如果有一个更新是将前两个分支更新为SF->SD
,SD->DC
,则另一个更新是将最后两个分支更新为LA->SJ
,SJ->NY
,如果您允许update
而不是保存完整的模型实例,你会发现SF->SD
,LA->SJ
,SJ->NY
的行程中断。