如何有效地更新基于反向关系的计算字段?

时间:2021-03-22 09:29:24
class A(models.Model):
    def calculate(self):
        # calculate some field based on all self.b_set instances

class B(models.Model):
    a = models.ForeignKey(A)

I'd like saving an instance of B to cause a function to fire on A, but efficiently.

我想保存一个B的实例,使一个函数在a上启动,但是很有效。

A naive implementation would be to hook up to the post_save signal emitted by B instances then run b.a.calculate(), but it would call a.calculate() N times.

一个简单的实现是连接到B实例发出的post_save信号,然后运行b.a.a calculate(),但是它会调用a.a calculate() N次。

Does anybody have any suggestions for how to implement this more efficiently?

对于如何更有效地实现这个目标,有人有什么建议吗?

I'm hitting a roadblock because I'm not sure how I would determine when the last B instance was successfully updated after which I'd want the A instance run its potentially expensive calculate() function.

我遇到了一个障碍,因为我不知道如何确定最后一个B实例何时被成功更新,然后我希望a实例运行它可能昂贵的compute()函数。

My best idea so far might be a "changed" flag on A and have a cron job pick up which A models need to be updated, but I wish it could be more accurate.

到目前为止,我最好的想法可能是在a上有一个“改变”的标志,并且有一个cron作业,这是一个需要更新的模型,但是我希望它能更准确。

1 个解决方案

#1


2  

If you have a formula x = a+b+c then you would always want to recalculate x after any of the arguments a,b or c changes. In your model above, if the calculated field value in model A depends on the relationships in model B then you would always want to recalculate after one of B instances change. However that does not necessary means the post_save will run N times. It will only run once every time one of B instances get saved.

如果你有一个公式x = a+b+c那么你总是希望在参数a b或c发生变化后重新计算x。在上面的模型中,如果模型A中计算的字段值取决于模型B中的关系,那么您总是希望在其中一个实例发生更改后重新计算。然而,这并不意味着post_save将运行N次。它只在每次保存一个B实例时运行一次。

If B has many fields that don not affect the expensive A.calculate() function, then adding a temporary checksum around the B's fields that matter to calculate and store the value as a new B field. Your post_save then can recalculate the checksum to see whether A.calculate() needs to run again or not.

如果B有许多不影响昂贵的a .calculate()函数的字段,那么在B的字段周围添加一个临时校验和,这些字段很重要,可以将值作为新的B字段来计算和存储。然后,您的post_save可以重新计算校验和,看看是否需要再次运行A.calculate()。

#1


2  

If you have a formula x = a+b+c then you would always want to recalculate x after any of the arguments a,b or c changes. In your model above, if the calculated field value in model A depends on the relationships in model B then you would always want to recalculate after one of B instances change. However that does not necessary means the post_save will run N times. It will only run once every time one of B instances get saved.

如果你有一个公式x = a+b+c那么你总是希望在参数a b或c发生变化后重新计算x。在上面的模型中,如果模型A中计算的字段值取决于模型B中的关系,那么您总是希望在其中一个实例发生更改后重新计算。然而,这并不意味着post_save将运行N次。它只在每次保存一个B实例时运行一次。

If B has many fields that don not affect the expensive A.calculate() function, then adding a temporary checksum around the B's fields that matter to calculate and store the value as a new B field. Your post_save then can recalculate the checksum to see whether A.calculate() needs to run again or not.

如果B有许多不影响昂贵的a .calculate()函数的字段,那么在B的字段周围添加一个临时校验和,这些字段很重要,可以将值作为新的B字段来计算和存储。然后,您的post_save可以重新计算校验和,看看是否需要再次运行A.calculate()。