Please enable Javascript to view the contents

Django 信号

 ·  ☕ 3 分钟

1. 基本概念

Django内置了一个信号分发器。信号可以帮助解耦程序模块。在应用中其他地方发生某事件时,通知指定函数。信号允许某些 senders 通知一组 receivers 已经发生的行为。

2. 信号使用

2.1 声明信号

在使用信号之前,首先得创建信号实例,声明信号的接收参数列表。django.dispatch.Signal是Django提供的信号类,其构造方法接收一个参数providing_args,指明信号包含的参数。

1
2
3
 from django.dispatch import Signal
# 声明一个名为mysignal的信号实例
 mysignal=Signal(providing_args=['user'])

2.2 发送信号

当需要通知接收者处理信号时,首先需要发送者发送一个signal。Signal类提供了两种方法,用于发送信号。

1
2
Signal.send(sender, **named)
Signal.send_robust(sender, **named)

两种方法都返回一个含有二元组的列表 [(receiver, response), … ],表示全部的接收函数和响应值。不同之处在于异常处理部分,send( )不会捕捉receiver产生的异常,而send_robust( )会。

1
2
3
4
 def home(request):
     mysignal.send(sender=None,user=request.user)
     # send方法第一个参数为sender,可以是对象.__class__、self、直接类名
     return HttpResponseNotAllowed('')

2.3 关联处理函数

第一种,使用connect方法。

1
Signal.connect(receiver, sender=None, weak=True, dispatch_uid=None)
  • receiver:signal的接收者
  • sender:signal的发送者
  • weak:Django默认将signal处理器当成弱引用存储。因此,如果接收函数是本地函数的话,有可能被垃圾回收。为防止这种情况,需要指定weak=False。
  • dispatch_uid:信号有可能重复发送的情况下,信号处理器的唯一标识 定义一个receiver(也可以说是一个call_back函数):
1
 mysignal.connect(record)

第二种,使用装饰器。

1
2
3
4
5
6
 from django.dispatch import receiver

 @receiver(mysignal)
 def record(sender,user,**kwargs):
     #执行函数第一个参数为sender
     print user.username

通过装饰器修饰,可以指定信号的处理函数。receiver也接受sender参数,仅处理指定发送者的信号。

第三种,使用dispatcher。

1
2
3
from django.db.models.signals import post_save
from django.dispatch import dispatcher  
dispatcher.connect(receiver=record, signal=post_save, sender=Mymodel) 

dispatcher显式的指出了处理函数,信号,发送者。

2.3 处理信号

信号的处理是通过调用处理函数实现的。

1
2
def callback_func(sender, **kwargs):
    pass

所有的信号处理函数,都必须接收一个sender参数,以及通配符关键字参数(**kwargs)

2.4 断开信号

1
Signal.disconnect(receiver=None, sender=None, weak=True, dispatch_uid=None):

如果接收器成功断开,返回 True ,否则返回False。

3. Django内置信号

Django内置的信号是已经实例化的Signal类。在使用时,省掉了声明信号,发送信号两个流程。将Django内置的信号直接关联上自定义的处理函数,即可使用。下面是Django内置信号列表:

django.db.models.signals

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    pre_init                    # django的modal执行其构造方法前,自动触发
    post_init                   # django的modal执行其构造方法后,自动触发
    pre_save                    # django的modal对象保存前,自动触发
    post_save                   # django的modal对象保存后,自动触发
    pre_delete                  # django的modal对象删除前,自动触发
    post_delete                 # django的modal对象删除后,自动触发
    m2m_changed                 # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
    class_prepared              # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
    pre_migrate                 # 执行migrate命令前,自动触发
    post_migrate                # 执行migrate命令后,自动触发
    pre_syncdb                 # 执行syncdb命令前,自动触发
    post_syncdb               # 执行syncdb命令后,自动触发

django.core.signals

1
2
3
4
    request_started             # 请求到来前,自动触发
    request_finished            # 请求结束后,自动触发
    got_request_exception       # 请求异常后,自动触发
    setting_changed        # settings发生改变时,自动触发

django.test.signals

1
    template_rendered           # 使用test测试渲染模板时,自动触发

django.db.backends.signals

1
    connection_created          # 创建数据库连接时,自动触发

例如,需要在每次完成请求后,进行某些操作,可以这样写:

1
2
3
4
5
from django.core.signals import request_finished
from django.dispatch import receiver
    @receiver(request_finished)
    def callback_func(sender,**kwargs):
        print('request finished')

4. 参考

  • 1.http://python.usyiyi.cn/translate/django_182/topics/signals.html
  • 2.http://lilongzi.blog.51cto.com/5519072/1906557

微信公众号
作者
微信公众号