web-dev-qa-db-ja.com

post_saveシグナルが呼び出されていません

関連する質問はすべて読みました。

2つのDjango=プロジェクトがあり、シグナルは1つで正常に機能しますが、2つ目では機能しません(それぞれ、コピーして貼り付けたコードと名前を変更しただけです)。

Orderモデルを使用した注文アプリがあります。アプリはINSTALLED_APPS設定に含まれています。

Apps.pyにアプリ構成があります:

from Django.apps import AppConfig


class OrdersConfig(AppConfig):
    name = 'orders'

    def ready(self):
        super(OrdersConfig, self).ready()

        # noinspection PyUnresolvedReferences
        import signals

__init__.py

default_app_config = 'orders.apps.OrdersConfig'

そして最後に、signals.py:

@receiver(post_save, sender=Order)
def order_save(sender, instance, created, **kwargs):
    print 'Post save'
    if created:
        print 'Created'
        send_email_new_order.delay(settings.MODERATOR_EMAIL, instance.pk)

そして、シグナルは呼ばれません。どうして?

Django 1.10.3。

18
int_32

Post_saveはいつ起動されますか?

ドキュメントの内容:saveメソッドの最後。

実際の意味:saveメソッドが正常に完了したとき。

信号が発生しないのはいつですか?

  1. saveメソッドがオブジェクトを正常に保存しなかった場合(IntegrityErrorが発生したときなど)
  2. MyModel.objects.update()を呼び出すとき
  3. saveメソッドをオーバーライドし、スーパークラスメソッドの呼び出しを忘れた場合。
  4. シグナルレシーバーが正常に登録されていない場合。

レシーバーの登録方法

最も簡単なのは、これまでと同じように@receiverデコレータを使用することです。代替は使用することです

from Django.db.models.signals import pre_save

pre_save.connect(order_save, sender='app_label.MyModel')

このコードはどこに配置する必要がありますか?

今日、 manual は次のように述べています

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

このため、このインスタンスで、signals.pyというファイルを作成し、その中にコードを配置して、AppConfigクラスとreadyメソッドの問題をすべて解決したのは、おそらくそのためです。しかしおかしなことに、 Django 1.6マニュアル はこう言っています:

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

したがって、シグナルレシーバーの登録に問題がある場合は、実際にコードをmodels.pyまたはviews.pyに配置して、AppConfigからビットを除外することができます(AppConfigを完全に削除することもできます)。

AppConfigで登録を実行したい場合で、@recieverやインポートで問題が発生した場合は、

from Django.db.models.signals import pre_save
from app_label.signals import my_reciever

def ready(self):
    pre_save.connect(my_reciever, sender='app_label.MyModel')

繰り返しを避ける方法は?

シグナルは2回発生しますか?レシーバーの登録は1回だけにしてください。 AppConfigに登録する場合は、models.pyから除外し、逆も同様です

21
e4c5

正しいsignalsがインポートされていることを確認しますか? (print('hi, signals here')モジュール内?)

完全に修飾されたインポート(import orders.signals)または相対的なもの(import .signals as signals)も。

5
AKX

signalsという名前の別のアプリはありますか?

readyメソッドで相対インポートを試してください:from . import signals

4
jatinderjit