web-dev-qa-db-ja.com

Django post_save信号は非同期ですか?

私はソーシャルネットワークのような「いいね」機能を持っています。ユーザーは星/ハート/好きなものとしてマークするコンテンツをクリックします。それはajaxで行われ、高速でなければなりません。ここでの唯一の問題は、いくつかの理由で、「いいね」ごとにいくつかのタスクを実行する必要があり、それらが「いいね」ビューで直接コーディングされていることがわかり、速度が遅くなることです。シグナルを使用してこれらのタスクの実行を非同期にして、タスクが完了するのを待たずにビューがjsonをすぐにJavaScriptに送信できるようにすることを考えています。私は「いいね」の信号を作成し始めましたが、Djangoの信号は非同期ではなく、同じ結果になることに気づきました。ビューは、信号が終了して応答を返すまで待機する必要があります。だから、あちこちで説明されているように、その信号を非同期にすることもできますが、「like」モデルにpost_save信号も使用しますが、信号が実行される前にビューが終了できるかどうか疑問に思いますか?

37
Bastian

あなたが欲しいのはスレッドです。使い方はとても簡単です。あなただけのサブクラスthreading.Threadおよびrunメソッドを記述します。

import threading

class LikeThread(threading.Thread):
    def __init__(self, user, liked, **kwargs):
        self.user = user
        self.liked = liked
        super(LikeThread, self).__init__(**kwargs)

    def run(self):
        # long running code here

次に、タスクを実行する準備ができたら、次のコマンドを実行します。

LikeThread(request.user, something).start()

残りのビューコードなどは、再開して応答を返します。スレッドは、完了するまで喜んでその作業を行い、その後終了します。

完全なドキュメントを参照してください: http://docs.python.org/library/threading.html

26
Chris Pratt

celery (またはより具体的には Django-celery )も確認してください。非同期タスクスケジューラ/ハンドラです。そのため、post_saveシグナルハンドラーがタスクを作成し、それがセロリを介して取得および実行されます。そうすれば、別のマシンやマシンのバッチであっても、重い作業が非同期で実行されている間も、スピーディなアプリケーションを利用できます。

42
Bouke

うーん、まずDjangoのシグナルは非同期ではありません。特定のケースではpost_saveは間違った方法です。最も簡単な方法は、Ajaxリクエストを発行して、好きなアクションを実行し、応答を待たないビューを表示することです。代わりに、リクエストを発行した直後にview/htmlを変更します。

もちろん、そのためには、ユーザーがこのアイテムを高く評価できること、および要求が失敗しないことを事前に知っておく必要があります。

7

async-signalsパッケージ( https://github.com/nyergler/async-signals )は、この問題を抽象化します。非同期シグナル関数を呼び出します。 Celeryが存在する場合、パッケージはそれを使用してワーカーから非同期で信号を発行します。また、Celeryが使用できない場合、パッケージは従来の同期方法で信号を送信します。

2
Chris Johnson