在指定update_fields时使用pre_save

5 投票
1 回答
2547 浏览
提问于 2025-04-18 15:57

我在MyModel上定义了一个pre_save函数,内容大概是这样的:

@receiver(pre_save, sender=MyModel)
def _mymodel_pre_save(sender, instance, **kwargs):
  if some_condition():
    instance.somecolumn = 'eggs'

也就是说,它希望能够修改MyModel实例的一些属性,并且当然希望这些修改在调用save()时能够保存下来。我觉得这是一种比较常见的pre_save函数用法。只要save()调用时没有指定update_fields,这个方法是没问题的。

我在想,现在有没有什么安全又合理的方法,可以在调用MyModel实例的save()时使用update_fields。如果我直接调用:

myinstance = MyModel.objects.get(id=100)
myinstance.othercolumn = 'spam'
myinstance.save(update_fields=['othercolumn'])

生成的UPDATE语句会是这样的:

UPDATE "myapp_mymodel" SET "othercolumn" = 'spam' WHERE "myapp_mymodel"."id" = 100

但是这样就会漏掉pre_save中对"somecolumn"的更新。我想这个情况可以通过在pre_save内部检查update_fields(它作为一个frozenset提供)来发现,但我看不出pre_save有什么办法可以强制执行它想要的更改,尤其是在调用者指定了更严格的update_fields的情况下,就像上面的例子那样。有没有什么解决办法呢?

1 个回答

3

这里有一个解决方法:

@receiver(pre_save, sender=MyModel)
def _mymodel_pre_save(sender, instance, **kwargs):
  if some_condition():
    instance.somecolumn = 'eggs'
    instance.save()

注意这里多了一次 "instance.save()" 的调用。

但是你必须确保在执行了 "instance.somecolumn = 'eggs'" 之后,some_condition() 不再为真。如果不这样做,就会导致不断循环调用保存和预保存的操作。

撰写回答