未调用 post_save 信号
Posted
技术标签:
【中文标题】未调用 post_save 信号【英文标题】:post_save signal isn't called 【发布时间】:2017-04-06 09:08:27 【问题描述】:我已经阅读了所有相关问题。
我有两个 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.
【问题讨论】:
尝试在模型末尾定义信号。 【参考方案1】:什么时候会触发 post_save?
文档内容:在保存方法的末尾。
真正含义:在save方法成功完成的最后。
什么时候不触发信号?
-
如果
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
中使用,反之亦然
【讨论】:
如果你把你的信号放在你的模型文件中,是 sender=self 吗?【参考方案2】:您确定导入了正确的signals
吗? (print('hi, signals here')
在模块中?)
您可能还想使用绝对合格的导入 (import orders.signals
) 或相对的导入 (import .signals as signals
)。
【讨论】:
嗯,用打印检查,它被调用了两次——可以吗? 这应该不是问题。【参考方案3】:您是否还有另一个名为 signals
的应用程序?
在ready
方法中尝试相对导入:from . import signals
【讨论】:
以上是关于未调用 post_save 信号的主要内容,如果未能解决你的问题,请参考以下文章
从 django post save 信号产生一个线程可以吗?