在Django模型中发送和接收信号

时间:2018-08-31 10:32:24

标签: python django django-signals

我正在使用Django 2.0.8和Python 3.5。我希望能够在将对象保存到数据库时发送和接收自定义信号。

我遵循了listening to signalscore signals bundled with Django上的Django文档-但是,我无法使我的示例生效。

这是我到目前为止所拥有的:

myapp / models.py

from django.db import models
import django.dispatch

my_signal = django.dispatch.Signal(providing_args=["name"])

class Foo(models.Model):
    name = models.CharField(max_length=16)

def save(self, *args, **kwargs):
    try:
        # Call the "real" save() method.
        super().save(*args, **kwargs)  

        # Fire off signal         
        my_signal.send(sender=self.__class__, name=self.name)

    except Exception as e:
        print ('Exception:', e)
        #pass

myapp / signals.py

from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Foo


@receiver(post_save, sender=Foo)
def foo_handler(sender, **kwargs):
    print('Foo Signal Recieved!')
    print(kwargs)

myapp / app.py

class MyappConfig(AppConfig):
name = 'myapp'
label = 'myapp'

def ready(self):
    import myapp.signals

样品用量

from myapp.models import Foo

foo = Foo(name='Homer Simpson')
foo.save() # Object is saved, but event is not fired!

谁能解释为什么不发射信号?

3 个答案:

答案 0 :(得分:6)

似乎您需要Django提供的两个功能。 signalcontenttypes

所以请先阅读文档

模型活动内容类型有关,似乎您错过了object_id字段,该字段指示正在填充哪个模型实例。

对于每个粗体操作,都将创建一个 Activity 实例。这部分只是用 signal.py

编写的代码

信号:信号必须连接每个具体模型。幸运的是,请参见装饰器receiver的源代码。

我们有一个信号列表[post_save,post_delete]和一个模型列表(FoodooChile,FooBarChile)进行连接。

在post_save中,已创建的参数表示该操作是创建还是更新。

最后,通常我们将信号文件导入urls.py,也许不是最佳实践。


它也与您的settings.py有关。使用{{1}中的'myapp.apps.MyappConfig'替换myappsettings.py中定义default_app_config = 'myapp.apps.MyappConfig'。上面评论中的链接对此进行了详细说明

答案 1 :(得分:0)

  1. myapp.signals中,您有一个接收器来处理未连接到您的信号的 post_save 信号(@receiver(post_save, sender=Foo))。
  2. 确保您在应用程序default_app_config = 'myapp.apps.MyappConfig'
  3. __ init __。py 中使用了应用程序配置
  4. 要连接到您创建的信号,请在Signals.py文件中尝试以下操作:

    @receiver(my_signal)
        def my_handler(name, **kwargs):
            print(name)
    

答案 2 :(得分:0)

可以说,您正在重新设计轮子,但只能将其放在购物车的一侧。

post_save信号总是在保存时发送,因此定义自己的信号是过大的。我知道您在那里有参数,但是接收者已经有sender参数,它是保存的对象,因此您只需执行sender.name即可获得所需的值。

除此之外,您还存在语法错误,没有缩进模型的自定义保存功能。我不知道这是您的问题中的格式错误,还是代码中的格式错误。无论哪种方式,如果您只是放下自定义信号,都应该起作用。

型号

from django.db import models
import django.dispatch


class Foo(models.Model):
    name = models.CharField(max_length=16)

信号

from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Foo


@receiver(post_save, sender=Foo)
def foo_handler(sender, **kwargs):
    print(sender.name)

应用

class MyappConfig(AppConfig):
name = 'myapp'
label = 'myapp'

def ready(self):
    import myapp.signals

样品

from myapp.models import Foo

foo = Foo(name='Homer Simpson')
foo.save()