156

djangoプロジェクトでシグナルリスナーの実装を始めたところです。私はそれらが何であるか、そしてそれらをどのように使用するかを理解しています。どこに置けばいいのかわからない。djangoサイトのドキュメントには次のように書かれています。

このコードはどこにあるべきですか?

信号処理と登録コードはどこにでも置くことができます。ただし、信号を送信する前に信号処理が登録されるように、モジュールが含まれているモジュールが早い段階でインポートされていることを確認する必要があります。これにより、アプリのmodels.pyはシグナルハンドラーの登録を行うのに適した場所になります。

それは良い提案ですが、models.pyに非モデルクラスまたはメソッドがあると、間違った方法で私をこすります。

では、シグナルハンドラーを保存および登録するためのベストプラクティス/ルールは何ですか?

4

7 に答える 7

264

これは、 Django1.7がリリースされたときにドキュメントに追加されました。

厳密に言えば、信号処理と登録コードは好きな場所に配置できますが、コードのインポートによる副作用を最小限に抑えるために、アプリケーションのルートモジュールとそのモデルモジュールを避けることをお勧めします。

実際には、シグナルハンドラーは通常、関連するアプリケーションのシグナルサブモジュールで定義されます。シグナルレシーバーは、アプリケーション構成クラスのready()メソッドに接続されています。Receiver()デコレータを使用している場合は、ready()内にsignalsサブモジュールをインポートするだけです。

Django 1.7で変更:ready()は以前のバージョンのDjangoには存在しなかったため、シグナル登録は通常モデルモジュールで行われました。

ベストプラクティスは、signalsサブモジュールのhandlers.pyでハンドラーを定義することです。たとえば、次のようなファイルです。

yourapp / signal / handlers.py

from django.db.models.signals import pre_save
from django.dispatch import receiver
from myapp.models import MyModel

@receiver(pre_save, sender=MyModel)
def my_handler(sender, **kwargs):
    pass

シグナルハンドラーを登録するのに最適な場所は、 ready()メソッドを使用して、シグナルハンドラーを定義するアプリのAppConfigです。これは次のようになります。

yourapp / apps.py

from django.apps import AppConfig

class TasksConfig(AppConfig):
    name = 'tasks'
    verbose_name = "Tasks"

    def ready(self):
        import yourproject.yourapp.signals.handlers #noqa

設定.pyのINSTALLED_APPSで直接指定するか__init__、アプリのでAppConfigを指定して、AppConfigを読み込んでいることを確認してください。詳細については、ready()のドキュメントを参照してください。

注:他のアプリにもリッスンするシグナルを提供している場合は__init__、シグナルモジュールのにそれらを配置します(例:次のようなファイル)。

yourapp / signal / __ init__.py

import django.dispatch

task_generate_pre_save = django.dispatch.Signal(providing_args=["task"])

次に、別のアプリが信号をインポートして登録することで信号を聞くことができますfrom yourapp.signals import task_generate_pre_save。信号をハンドラーから分離することで、物事をクリーンに保つことができます。

Django 1.6の手順:

それでもDjango1.6以下を使い続ける場合は、同じことを行います(yourapp / signal / handlers.pyでハンドラーを定義します)が、AppConfigを使用するのではなく、の__init__。pyを介してハンドラーをロードします。あなたのアプリ、例えば:

yourapp / __ init__.py

import signals

これは、循環インポートの問題を引き起こすことが多いため、ready()メソッドを使用するほど良くはありません。

于 2014-04-07T23:08:29.210 に答える
40

私は実際にそれらをモデル自体のクラスメソッドにするのが好きです。これにより、すべてが1つのクラス内に保持され、何もインポートすることを心配する必要がなくなります。

于 2010-04-27T08:14:31.767 に答える
40

私はこれに出くわしたばかりで、私の信号はモデルに関連していないので、ソリューションを追加すると思いました。

ログイン/ログアウトに関するさまざまなデータをログに記録しており、にフックする必要がありますdjango.contrib.auth.signals

シグナルハンドラーをsignals.pyファイルに入れ、モジュールファイルからシグナルをインポートしました。__init__.pyこれは、アプリが起動するとすぐに呼び出されると信じているためです(printステートメントでテストすると、設定ファイルが読み取られる前でも呼び出されることがわかります)。

# /project/__init__.py
import signals

およびsignals.pyで

# /project/signals.py
from django.contrib.auth.signals import user_logged_in

def on_logged_in(sender, user, request, **kwargs):
    print 'User logged in as: \'{0}\''.format(user)

user_logged_in.connect(on_logged_in)

私はDjango(/ python)にかなり慣れていないので、これはひどい考えだと言ってくれる人なら誰でも受け入れてくれます!

于 2012-07-14T12:55:25.897 に答える
13

プロジェクト/アプリケーションのレイアウトに関するベストプラクティスに関するこの記事を最近読んだところ、すべてのカスタムディスパッチャーシグナルを。というファイルに入れる必要があることが示唆されていますsignals.py。ただし、これらをどこかにインポートする必要があり、インポートが早いほど良いため、問題を完全に解決することはできません。

モデルの提案は良いものです。ファイル内のすべてをすでに定義しているので、signals.pyファイルの先頭に1行以上かかることはありません。admin.pyこれは、ファイルのレイアウト方法(上部にクラス定義、下部にすべてのカスタム管理クラスを登録するためのコード)に似ています。シグナルを定義してから、それらを同じファイルに接続します。

お役に立てば幸いです。最終的にそれはあなたが好むものに帰着します。

于 2010-04-27T07:36:20.913 に答える
9

各アプリのmodels.pyとsignals.pyはシグナルを接続するための推奨される場所ですが、私の意見では、シグナルとハンドラーをディスパッチし続けるための最良のソリューションではありません。ディスパッチは、djangoで発明されたシグナルとハンドラーの理由である必要があります。

私は長い間苦労していましたが、最終的に解決策を見つけました。

アプリフォルダにコネクタモジュールを作成します

だから私たちは持っています:

app/
    __init__.py
    signals.py
    models.py
    connectors.py

app / connectedors.pyで、シグナルハンドラーを定義し、それらを接続します。例を示します。

from signals import example_signal
from models import ExampleModel
from django.db.models.signals import post_save, post_delete

def hanndler(sender, *args, **kwargs):
    pass

post_save.connect(hander, sender=ExampleModel)

次に、models.pyで、ファイルの最後に次の行を追加します。

from app import connector

ここですべてが行われます。

このようにして、signals.pyにシグナルを配置し、connectors.pyにすべてのハンドラーを配置できます。モデルや信号に混乱はありません。

それが別の解決策を提供することを願っています。

于 2013-05-05T06:55:01.313 に答える
4

についての小さなリマインダーAppConfig。設定することを忘れないでください:

# yourapp/__init__.py

default_app_config = 'yourapp.apps.RockNRollConfig'
于 2018-08-13T11:02:24.740 に答える
3

すべてのモデルが定義された後signals.py、それらを別のファイルに保存します。models.pyそれらをインポートし、モデルをシグナルに接続します。

signals.py

#  necessary imports

def send_mail_on_save(<args>):
    # code here 

models.py

# imports
class mymodel(models.Model):
    # model here

# import signals
from signals import send_mail_on_save
# connect them 
post_save.connect(send_mail_on_save,sender=mymodel)

これにより、論理的な分離が可能になります。もちろん、 models.pyに保持することに問題はありませんが、 この方法の方が管理しやすくなります。

お役に立てれば!!

于 2016-08-25T12:01:31.287 に答える