2009-06-04 63 views
16

有沒有什麼辦法可以在Django事務提交後運行一些代碼?在Django事務提交後運行代碼

我需要向rabbitmq服務器發送一些消息以進行脫機處理,但消息在Django事務提交之前傳遞給消費者。

我的消息是在模型的post_save信號中發送的。我正在尋找的是一種類似的機制,使用信號或其他方式,在提交後執行代碼(如果事務失敗,則不執行任何操作)。

我還沒有在Django中找到任何通用的方法。你有什麼想法?

+1

我有一個simmilar問題。在post_save上,發佈者(進程1)保存任務狀態併發布消息。使用者(進程2)收到消息並更新任務狀態,但尚未在數據庫中。有效的是讓消費者在收到消息後一兩秒鐘睡覺。無論如何感覺骯髒。 – ohnoes 2010-01-19 11:35:43

+0

掙扎了4個小時之後,我從這個問題中發現,在transaction.commit()之後我們不能擁有代碼,現在我的代碼運行良好。謝謝。 – zubinmehta 2011-12-26 20:10:30

+0

相關故障單:https://code.djangoproject。com/ticket/14051 – guettli 2012-05-11 11:08:50

回答

11

UPDATE 2:django-transaction-hooks是merged into Django core,並在Django 1.9版中發佈。

UPDATEdjango-transaction-hooks解決了這個問題。

我不相信有一個乾淨的方式來做到這一點;至少我想不出一個。您可以monkeypatch django.db.transaction.commit發送自定義信號;不漂亮,但我認爲它會工作。

django-developers mailing list上引用此用例也許會很有趣。開發人員通常不願意添加新的信號,但您可能在這裏有一個很好的例子(並且來自核心開發人員的反駁可能包括對如何解決您的情況的有用建議)。不過,如果你等到1.1出來後,你更有可能得到迴應。

1

一種可能性是對事務中間件進行子類化,以便在提交時發送自定義信號。你的代碼可以監聽那個信號,而不是post_save。

5

希望這可以幫助使用Django 1.9或更高版本的用戶。由於1.9 on_commit可用。

所以基本上你會做這樣的:

from django.db import transaction 

transaction.on_commit(
    lambda: send_msg_to_rabbitmqp(param1, param2, ...) 
) 

如果您想保留post_save,你仍然可以使用on_commit

@receiver(pre_save, sender=MyModel) 
def my_handler(sender, instance, created, **kwargs): 
    transaction.on_commit(
     lambda: send_msg_to_rabbitmqp(instance.id) 
    )