【问题标题】:post_save signal isn't called未调用 post_save 信号
【发布时间】: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.

【问题讨论】:

  • 尝试在模型末尾定义信号。

标签: python django django-models django-signals


【解决方案1】:

什么时候会触发 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')

这段代码应该放在哪里?

如今,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 中使用,反之亦然

【讨论】:

  • 如果你把你的信号放在你的模型文件中,是 sender=self 吗?
【解决方案2】:

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

您可能还想使用绝对合格的导入 (import orders.signals) 或相对的导入 (import .signals as signals)。

【讨论】:

  • 嗯,用打印检查,它被调用了两次——可以吗?
  • 这应该不是问题。
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 2017-10-10
    • 1970-01-01
    • 2013-06-13
    • 2012-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    相关资源
    最近更新 更多