25

Djangoでトランザクションがコミットされた後にコードを実行する方法はありますか?

オフライン処理のためにいくつかのメッセージをrabbitmqサーバーに送信する必要がありますが、Djangoトランザクションがコミットされる前にメッセージがコンシューマーに届きます。

私のメッセージは、モデルのpost_saveシグナルで送信されます。私が探しているのは、シグナルなどを使用して、コミット後にコードを実行する(トランザクションが失敗した場合は何もしない)同様のメカニズムです。

Djangoでそれを行う一般的な方法は見つかりませんでした。あなたはなにか考えはありますか?

4

5 に答える 5

21

django-transaction-hooksは、Django <1.9のこの問題を解決し、機能はDjango1.9以降に組み込まれています。

from django.db import transaction

def do_something():
    pass  # send a mail, invalidate a cache, fire off a Celery task, etc.

transaction.on_commit(do_something)
于 2009-06-04T15:13:00.910 に答える
14

これがDjango1.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)
    )
于 2016-01-12T12:06:18.153 に答える
5

モンキーパッチdjangoによって トランザクションシグナル(post_commitおよび)を実装しました:http: //gist.github.com/247844post_rollback

于 2009-12-03T03:15:34.360 に答える
1

これに対する解決策については、 django-celery-transactionsをご覧ください。

最近、基になるシグナルコードコードをスタンドアロンアプリdjango-db-signalsに分割してリファクタリングしました。

于 2012-12-24T06:32:53.263 に答える
1

1つの可能性は、トランザクションミドルウェアをサブクラス化して、コミット時にカスタムシグナルを送信することです。コードは、post_saveではなく、そのシグナルをリッスンできます。

于 2009-06-04T13:19:48.800 に答える