jasper的技术小窝

关注DevOps、运维监控、Python、Golang、开源、大数据、web开发、互联网

谈谈django中的signals

作者:jasper | 分类:django | 标签:     | 阅读 3039 次 | 发布:2014-10-06 5:22 p.m.

在开发中,你可能常常会有这样的需求,在发生某个动作的时候,我们希望能自动去执行一些后续的动作。当然我们可以把两个动作写在一起,但是如果前面的动作不止一种呢,这段逻辑就会写很多次,在django中有个叫做signals,能很好地完成这个需求。当事件触发时,相应的signal就会通知所有注册的receivers得到调用,这不就是传说中的观察者模式吗。signals(中文翻译为信号,有的也翻译为异步)是在django中的特有特性,在python中是没有的,下面就来说一说它的具体用法。

django的signals内部自己定义了几个信号量, 就是几种事情会触发信号发生传递.。有这么几种:

1、Model signals

  • pre_init 某个实例马上要初始化了
  • post_init 某个实例已经初始化了
  • pre_save 个实例即将要保存入库了
  • post_save 某个实例即已经保存入库了
  • pre_delete 某个实例即将要删除了
  • post_delete 某个实例即已经删除了
  • class_prepared 某个class准备好了
  • m2m_changed 模型的ManyToManyField改变时触发

2、Management signals

  • post_syncdb 数据库已经同步完成了

3、Request/response signals

  • request_started 请求开始
  • request_finished 请求结束
  • got_request_exception 请求发生异常了

4、Test signals

  • template_rendered template已经渲染好了

可以看出,大部分都是都是和数据库有关的操作,举个例子吧:

signal的监听:

signal.connect(receiver[, sender=None, weak=True, dispatch_uid=None])

  1. receiver参数:一个signal的接受者,为一个函数
  2. sender参数:一个signal的发送者,即触发者
  3. weak参数:django默认将signal处理器当成弱引用存储。因此,如果接收处理器是本地函数的话,是有可能被垃圾回收的。为防止这种情况,需要指定weak=False
  4. dispatch_uid参数:信号有可能重复发送的情况下,信号处理器的唯一标识 定义一个receiver(也可以说是一个call_back函数):
 def my_callback(sender, **kwags):
    print("model saved")

将这个receiver注册到signal中:

方法一:

django.db.models.signals.post_save
post_save.connect(my_callback, sender=Mymodel)

方法二:

django.db.models.signals.post_save
from django.dispatch import dispatcher  
dispatcher.connect(my_callback, signal=post_save, sender=Mymodel) 

方法三:(将sender和receiver写在一起了)

django.db.models.signals.post_save
from django.dispatch import receiver
    @receiver(post_save, sender=Mymodel)
    def my_callback(sender, **kwags):
        print("model saved")

这样就能在每条记录保存后打印出相应的内容了。 当然,我们也能signal的自定义和发送:

import django.dispatch
something_done = django.dispatch.Signal(providing_args=["xxx", "yyy"])
#  发送
class SomethingStore(object):
     ...
     def send_something(self, xxx, yyy):
          something_done.send(sender=self.__class__, xxx=xxx, yyy=yyy)
            ...

这样something_done就是一个signal了,也能像前面提到的那些signal一样,注册到相应的触发事件之中。 2种发送方法中

Signal.send(sender, **kwargs)
Signal.send_robust(sender, **kwargs)

区别是send当发生异常时,会抛出,所以不是所有的接收者都一定会接收到signal send_robust会把异常封装成Python的Exception类,并且所有的接收者都一定会接收到signal

就这样吧。。。。。


转载请注明出处:http://www.opscoder.info/django_signals.html

其他分类: