Search code examples
pythondjangodjango-modelsdjango-signals

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. 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.

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.

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?


Solution

  • 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

    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.