简体   繁体   English

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

[英]Django - Model property methods vs signals for field calculation

I have a model that does some basic aggregation of some values on a m2m field.我有一个模型可以对 m2m 字段上的某些值进行一些基本聚合。 I can achieve this by doing the calculation in a Model method, in which case the results would be stored in a model attribute.我可以通过在模型方法中进行计算来实现这一点,在这种情况下,结果将存储在模型属性中。

Or I can do the calculation in a pre_save signal function, and then the result would be stored in a model field.或者我可以在 pre_save 信号函数中进行计算,然后将结果存储在模型字段中。

I want to know are there are any cons to using signals?我想知道使用信号有什么缺点吗? or in which cases it would be better to use a model property method?或者在哪些情况下使用模型属性方法会更好?

I understand that the calculations will run at different times, with the signal function running when save() is called, and the model method running automatically.我知道计算将在不同的时间运行,调用 save() 时会运行信号函数,并且模型方法会自动运行。

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)

The signal approach has the benefit of resulting in a model field rather than a model attribute, which makes it easier use in Parent or related models for aggregation.信号方法的好处是产生模型字段而不是模型属性,这使得它更容易在父模型或相关模型中用于聚合。 So why would one ever use a Model method over a model signal?那么为什么要在模型信号上使用模型方法呢?

The difference is that the @property will be calculated every time you access it, and the signal one will be calculated once and then stored, if you're not using the right indices they can have a big difference in performance不同之处在于每次访问时都会计算@property ,并且将计算一次信号然后存储,如果您没有使用正确的索引,它们可能会对性能产生很大的影响

Another difference is that if you use CartItem.objects.update , signals won't run, so you would end up with invalid data, same thing if you updated the object outside of Django directly through SQL.另一个区别是,如果您使用CartItem.objects.update ,信号将不会运行,因此您最终会得到无效数据,如果您直接通过 SQL 在 Django 之外更新对象,则同样如此。

I'm VERY new to django, but I was asking a similar question.我对 Django 很陌生,但我问了一个类似的问题。 I had 2 time fields and needed the difference between them.我有 2 个时间字段,需要它们之间的差异。 My first try was with a property which worked reasonably well until I realized I needed to be able to easily get a total of that difference across a queryset.我的第一次尝试是使用一个运行良好的属性,直到我意识到我需要能够轻松地获得整个查询集的总差异。

I ended up implementing a pre_save signal to set the value of the field.我最终实现了一个 pre_save 信号来设置字段的值。 In my use case, the data doesn't change frequently, so it made sense.在我的用例中,数据不会经常更改,所以这是有道理的。 Then I created a property on the queryset to aggregate a sum.然后我在查询集上创建了一个属性来聚合总和。 This way I can filter first and get a sum across the subset.这样我就可以先过滤并得到子集的总和。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM