post_save信号未被调用

时间:2016-11-22 15:47:17

标签: python django django-models django-signals

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

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

我有订单模型的订单应用。应用程序包含在INSTALLED_APPS设置中。

我在apps.py中有app配置:

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。

3 个答案:

答案 0 :(得分:18)

何时会触发post_save?

文档说明:保存方法结束时。

它的真正含义:在成功完成保存方法的最后。

什么时候不发射信号?

  1. 如果save方法未成功保存对象(例如发生IntegrityError时)
  2. 致电MyModel.objects.update()
  3. 当您覆盖save方法并忘记调用超类方法时。
  4. 当您的信号接收器未成功注册时。
  5. 如何注册接收器

    最简单的方法是使用@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 manual说:

      

    您可以将信号处理和注册码放在任何您喜欢的地方。   但是,您需要确保它所在的模块得到   早期导入,以便之前注册信号处理   需要发送任何信号。这使你的应用程序的models.py很好   放置信号处理程序的地方。

    因此,如果您在注册信号接收器时遇到问题,您实际上可以尝试将代码放在models.pyviews.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')
    

    如何避免重复?

    信号是否会被触发两次?确保只注册一次接收器。如果您在AppConfig中注册,请将其保留为models.py和反之豁免

答案 1 :(得分:4)

您是否仍然确定导入了正确的signals? (print('hi, signals here')在模块中?)

您可能也希望使用绝对限定的导入(import orders.signals)或相对导入(import .signals as signals)。

答案 2 :(得分:4)

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

使用ready方法尝试相对导入:from . import signals