post_save信号未被调用

int*_*_32 17 python django django-signals django-models

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

我有两个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
Run Code Online (Sandbox Code Playgroud)

__init__.py:

default_app_config = 'orders.apps.OrdersConfig'
Run Code Online (Sandbox Code Playgroud)

最后,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)
Run Code Online (Sandbox Code Playgroud)

信号没有被调用.为什么?

Django 1.10.3.

e4c*_*4c5 21

什么时候post_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')
Run Code Online (Sandbox Code Playgroud)

该代码应放在何处?

如今,手册指出了这一点

严格地说,信号处理和注册代码可以在任何你喜欢的地方生活,尽管建议避免应用程序的根模块及其模型模块,以尽量减少导入代码的副作用.

这可能就是为什么在这种情况下你创建了一个名为signals.py的文件,并将你的代码置于其中,然后使用AppConfig类和ready方法解决了所有问题.但有趣的是,Django 1.6手册说:

您可以将信号处理和注册码放在任何您喜欢的地方.但是,您需要确保早期导入模块,以便在需要发送任何信号之前注册信号处理.这使您的应用程序的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')
Run Code Online (Sandbox Code Playgroud)

如何避免重复?

信号被触发两次吗?确保只注册一次接收器.如果您注册AppConfig,请将其保留,models.py并将其删除


AKX*_*AKX 5

您绝对确定正确signals的进口吗?(print('hi, signals here')在模块中?)

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