Django - 模型 属性 方法与用于字段计算的信号

Django - Model property methods vs signals for field calculation

我有一个模型可以对 m2m 字段上的某些值进行一些基本聚合。我可以通过在模型方法中进行计算来实现这一点,在这种情况下,结果将存储在模型属性中。

或者我可以在 pre_save 信号函数中进行计算,然后将结果存储在模型字段中。

我想知道使用信号有什么缺点吗?或者在哪些情况下使用模型 属性 方法会更好?

我知道计算会在不同的时间 运行,当调用 save() 时信号函数 运行ning 和模型方法 运行ning 自动。

class CartItem(models.Model):
    name = models.CharField(max_length=100)
    total_price = models.DecimalField(max_digits=10, decimal_places=2)

##Model Method Approach
    @property
    def price(self):
        return self.extras.all().aggregate(Sum('price'))['price__sum']

##Signal Approach
def set_total_price(sender, instance, **kwargs):
      instance.total_price= instance.extras.all().aggregate(Sum('price'))['price__sum'] 

pre_save.connect(set_total_price, sender=CartItem)

信号方法的好处是生成模型字段而不是模型属性,这使得它更容易在父模型或相关模型中用于聚合。那么,为什么人们会在模型信号上使用模型方法呢?

不同的是@property每次访问都会计算一次,而signal one会计算一次然后存储,如果你没有使用正确的索引,它们可能会有很大的影响性能差异

另一个区别是,如果你使用 CartItem.objects.update,信号不会 运行,所以你最终会得到无效数据,如果你直接通过 SQL.

我对 django 很陌生,但我问了一个类似的问题。我有 2 个时间字段,需要它们之间的区别。我的第一次尝试是使用 属性,它工作得相当好,直到我意识到我需要能够轻松地获得整个查询集的总差异。

我最终实现了一个 pre_save 信号来设置字段的值。在我的用例中,数据不会经常更改,所以这是有道理的。然后我在查询集上创建了一个 属性 来聚合总和。这样我可以先过滤并得到整个子集的总和。