目录

    1. 基本概念

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

    2. 信号使用

    2.1 声明信号

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

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

    2.2 发送信号

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

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

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

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

    2.3 关联处理函数

    第一种,使用connect方法。

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

    第二种,使用装饰器。

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

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

    第三种,使用dispatcher。

    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 处理信号

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

    def callback_func(sender, **kwargs):
        pass
    

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

    2.4 断开信号

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

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

    3. Django内置信号

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

    django.db.models.signals

        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

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

    django.test.signals

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

    django.db.backends.signals

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

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

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

    4. 参考