Django - проблема синхронизации post_save - как реализовать сигнал для действия "база данных сохранена завершена"

Мне кажется, что сигнал post_save срабатывает не тогда, когда весь процесс сохранения завершен в базе данных, а в конце вызова model.save().

Я сделал это наблюдение при выполнении следующего кода:

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()

В некоторых случаях этот код не обновлял проект total_value правильно, так как экземпляр (который я только что сохранил), запрашиваемый с PurchaseOrder.objects.filter (project = project, is_active = True), очевидно, не обновлялся. Таким образом, мне кажется, что поток обогнал метод сохранения экземпляра и запросил старую версию модели.

Я знаю, как преодолеть эту конкретную проблему (просто взять последнее значение из экземпляра, предоставленного сигналом post_save), но мне интересно, как можно создать сигнал post_save, который запускается, когда действие сохранения в базе данных завершено.

1 ответ

Решение

Вы правы, сигнал post_save выполняется в конце метода save(). Этот факт есть в документации Django:

django.db.models.signals.post_save

Как и pre_save, но отправляется в конце метода save().

Если ваше намерение состоит в том, чтобы использовать сигнал в нескольких областях, возможно, вам лучше написать свой собственный.

редактировать: лучшая ссылка на определения сигналов

Другие вопросы по тегам