我的模特:
class Order(models.Model):
property_a = models.CharField()
property_b = models.CharField()
property_c = models.CharField()
许多用户将通过管理员更改页面在短时间内访问给定记录,因此我遇到了并发问题:
用户1和2同时打开更改页面。假设加载页面时所有值都为空。用户1将property_a设置为“a”,将property_b设置为“b”,然后保存。一秒钟后,如果用户2更改属性b和c然后保存,它将悄悄地覆盖用户1的所有值。在这种情况下,property_a将返回为空白,b和c将是用户2放入的任何值。
我需要有关如何处理此问题的建议。如果我必须在模型中有一个版本字段,我如何将其传递给管理员,我在哪里进行检查以便我可以优雅地通知用户他们的更改无法保存,因为另一个用户修改了记录?有没有比向用户返回错误更无缝的方式?
答案 0 :(得分:0)
标准解决方案是阻止您的用户共享单个记录。目前还不清楚为什么这么多用户都在使用完全相同的Order
实例。
考虑Order
可能是一个复合对象,而且你已经把太多的东西放到了一个模型中。这是第一个 - 也是最好的 - 解决方案。
如果(出于莫名其妙的原因)你不会将其分解,那么你必须创建一个由两部分组成的更新事务。
重新查询数据。与原始查询比较为此用户的会话完成。
如果数据与原始查询不匹配,则其他人更改了该数据。用户的更改无效,回滚,清除,用户看到新查询。
如果数据匹配,您可以尝试提交更改。
上述算法具有竞争条件,通常通过低级SQL解决。请注意,它会使用户的工作无效,从而使其最具刺激性。
这就是为什么你的第一选择是分解模型以消除并发性。
我的模型有一个杂项备注字段
这是一个糟糕的设计。 (a)并发性因此场上的冲突而破坏。 (b)没有日志或评论历史。
项目(b)表示行为不端的用户可以恶意破坏这些数据。如果您将注释和注释保存为日志,则原则上可以限制用户仅更改自己的注释。
[在大多数带有“杂项说明”的数据库中,该字段已成为一种代价高昂,难以维护的责任,其中包含重要但不可能解析的数据。杂项是用户在应用软件之外发明自己的流程的地方。 ]
“杂项备注”必须被视为日志,具有无限数量的备注 - 日期戳记 - 由用户标识 - 追加到订单。
如果您只是将设计分区以将注释放在单独的表中,则可以解决并发问题。