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