2009-06-04 66 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) 
    )