在Django中提交事务后,有没有办法运行一些代码?
我需要向rabbitmq服务器发送一些消息以进行离线处理,但是在提交Django事务之前消息会传递给消费者。
我的消息是在模型的post_save信号中发送的。我正在寻找的是一种类似的机制,使用信号或其他东西,它将在提交后执行代码(如果事务失败,则不执行任何操作)。
我没有在Django中找到任何通用方法。你有什么想法吗?
答案 0 :(得分:10)
更新2 :django-transaction-hooks为merged into Django core并在Django 1.9版本中发布。
更新:django-transaction-hooks解决了这个问题。
我不相信有一种干净的方法可以做到这一点;至少我想不出一个。您可以使用monkeypatch django.db.transaction.commit发送自定义信号;不漂亮,但我认为它会起作用。
在django-developers mailing list上提出这个用例可能也很有趣。开发人员通常不愿意添加新信号,但是你可能在这里有一个很好的案例(来自核心开发者的反驳可能包括如何解决你的情况的有用建议)。如果你等到1.1出来之后,你更有可能得到答案。
答案 1 :(得分:7)
希望这可以帮助使用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)
)
答案 2 :(得分:5)
我通过猴子修补django实现了交易信号(post_commit
和post_rollback
):
http://gist.github.com/247844
答案 3 :(得分:1)
一种可能性是将事务中间件子类化,以便它在提交时发送自定义信号。你的代码可以监听那个信号,而不是post_save。
答案 4 :(得分:1)
请查看django-celery-transactions以获得此解决方案。
我最近完成了拆分并将基础信号代码重构为独立应用django-db-signals。