我已经阅读了所有相关问题。
我有两个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。
答案 0 :(得分:18)
文档说明:保存方法结束时。
它的真正含义:在成功完成保存方法的最后。
save
方法未成功保存对象(例如发生IntegrityError
时)MyModel.objects.update()
save
方法并忘记调用超类方法时。最简单的方法是使用@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.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')
信号是否会被触发两次?确保只注册一次接收器。如果您在AppConfig
中注册,请将其保留为models.py
和反之豁免
答案 1 :(得分:4)
您是否仍然确定导入了正确的signals
? (print('hi, signals here')
在模块中?)
您可能也希望使用绝对限定的导入(import orders.signals
)或相对导入(import .signals as signals
)。
答案 2 :(得分:4)
您是否还有另一个名为signals
的应用?
使用ready
方法尝试相对导入:from . import signals