2013-03-13 44 views
1

在我看來好像post_save信號觸發,而不是整個保存過程已完成在數據庫中,但在model.save()調用。Django - post_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信號,當數據庫中的保存操作最終確定。

+0

這個問題是相似的:http://stackoverflow.com/questions/950214/run-code-after-transaction-commit-in-django – 2013-03-13 12:20:29

+0

是的,你是對的。 – 2013-03-13 14:02:14

回答

1

你是對的,post_save信號在save()方法的末尾執行。這實際上是在Django docs

django.db.models.signals.post_save

像pre_save,但在save()方法結束時發送。

如果您的意圖是在多個區域使用信號,則可能更適合於write your own

編輯:更好的鏈接信號定義

+0

好吧,我想我會按照這個答案的建議:http://stackoverflow.com/a/951193/237690併發布功能請求到django郵件列表。在django的核心中看到這個特性會很棒。 – 2013-03-13 14:04:09

相關問題