it seems to me as if the post_save signal is triggered not when the entire save process has been finalized in the database, but at the end of the model.save() call.
I made this observation when executing the following code:
models.py
class PurchaseOrder(models.Model):
total_value = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
def purchase_order_post_save_handler(sender, instance, **kwargs):
project_po_value_update_thread = accounting.threads.ProjectPoValueUpdateThread(instance)
project_po_value_update_thread.start()
post_save.connect(purchase_order_post_save_handler, sender=PurchaseOrder)
threads.py
class ProjectPoValueUpdateThread(threading.Thread):
"""
thread to update the po.project with the latest po values
called via the save method of the purchase order
"""
def __init__(self, purchase_order):
self.purchase_order = purchase_order
threading.Thread.__init__(self)
def run(self):
"starts the thread to update project po values"
try:
project = self.purchase_order.project
#update active po budget
active_po_sum = PurchaseOrder.objects.filter(project=project, is_active=True).aggregate(total_value_sum=Sum('total_value'))
active_total_value_sum = active_po_sum['total_value_sum']
project.total_value = active_total_value_sum
project.save()
In some cases, this code did not update the project total_value correctly, as the instance (which I just saved) queried with PurchaseOrder.objects.filter(project=project, is_active=True) was obviously not updated. Thus it seems to me as the thread has overtaken the instance save method and queried an old version of the model.
I know how to overcome this specific problem (just take the latest value from the instance provided by the post_save signal), but I'm wondering how one could create a post_save signal that is triggered when the save action in the database finalized.