Django: How to trigger a function whenever certain objects are modified from the wagtail interface
I have a long list of "Quotation" objects.
The price of a quotation depends on dozens of children (and grand children) objects. The lowest one being the rate/hour.
When I change the children objects of a quotation like the rate/hour, the quotation price changes.
I would like to recalculate the price of each quotation that is impacted by any change I make on their consistuant objects automatically. I am using Wagtail for the object admin.
I am not sure about the way to do that, should I use signals? Wagtail hooks?
Wagtail models and pages are just Django models.
Are all children (and grand children) of the same model? In that case you could just register a post_save signal on the child model, but in general, I'd recommend using post_save only for things like sending an email when an object changes, unless you take the following things into consideration:
- This kind of processing can become very slow very quickly. If you have multiple quotations, you'll need to use an atomic transaction, otherwise you'll make a new db connection when saving every quotation.
- You'll also need to prefetch children and grandchildren, to prevent multiple database calls.
- When saving other models inside a post_save, you run the risk of creating an endless loop of post_save signals.
I think a better way would be to add a @property called price
on Quotation instead of storing the price in the database:
class Quotation(models.Model):
# Model fields here
...
@property
def price(self):
return sum([child.price for child in self.children])
This will only calculate a price when you call quotation.price
. You could speed up this calculation by prefetching children when receiving Quotations.