post_save 没有调用信号

post_save signal isn't called

我已经阅读了所有相关问题。

我有两个 Django 项目,信号在一个项目中工作正常,但在第二个项目中不起作用(我只是分别复制粘贴代码和更改名称)。

我有一个带有订单模型的订单应用程序。应用包含在 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.

您 aaaaa 绝对确定导入了正确的 signals 吗? (print('hi, signals here') 在模块中?)

您可能还想使用绝对限定导入 (import orders.signals) 或相关导入 (import .signals as signals)。

您是否还有另一个名为 signals 的应用程序?

尝试在 ready 方法中进行相对导入:from . import signals

post_save 什么时候被解雇?

文档说的是:在保存方法的末尾。

真正的意思是:在成功完成保存方法的最后。

什么时候不触发信号?

  1. 如果save方法没有成功保存对象(比如发生IntegrityError时)
  2. 当你打电话时 MyModel.objects.update()
  3. 当你覆盖save方法而忘记调用superclass方法时。
  4. 当你的信号接收器没有注册成功时。

如何注册接收器

最简单的方法是像您所做的那样使用 @receiver 装饰器。另一种方法是使用

from django.db.models.signals import pre_save

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

这段代码应该放在哪里?

如今,manual 指出

Strictly speaking, signal handling and registration code can live anywhere you like, although it’s recommended to avoid the application’s root module and its models module to minimize side-effects of importing code.

这可能就是为什么在这种情况下您创建了一个名为 signals.py 的文件并将您的代码放入其中并解决了 AppConfig class 和 ready 方法的所有问题。但有趣的是,Django 1.6 manual 说:

You can put signal handling and registration code anywhere you like. However, you’ll need to make sure that the module it’s in gets imported early on so that the signal handling gets registered before any signals need to be sent. This makes your app’s models.py a good place to put registration of signal handlers.

因此,如果您在注册信号接收器时遇到问题,您实际上可以尝试将您的代码放入 models.pyviews.py 并从 AppConfig 中省略这些位(甚至可能完全删除 AppConfig)

如果你想在 AppConfig 中进行注册,而你在 @reciever and/or 导入时遇到问题,你可以尝试

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')

如何避免重复?

信号是否被触发了两次?确保只注册接收器一次。如果您在 AppConfig 中注册它,请将其排除在 models.py 之外,反之亦然