Django 高级配置



Django 信号

django自带一套信号机制来帮助我们在框架的不同位置之间传递信息。也就是说,当某一事件发生时,信号系统可以允许一个或多个发送者(senders)将通知或信号(signals)发送给一组接受者(receivers)

信号系统三要素:

  • 信号 <class: django.dispatch.Signal > 的实例
  • 发送方 某一个信号的发送者
  • 接收方 一个或多个信号的接收者

信号的分类:

  • Django 内置信号, 框架内置的 Signal 实例, 发送 方 为 Django 框架
  • 自定义 信号 , 开发者 手动创建 Signal 实例, 且需指定发送方 和 接收方

Django 内置信号:

框架位置: 位于框架 signals.py 文件中。 例如 框架内置的各 app 目录下的 django\contrib\APP\signals.py 文件中 和django\core\signals.py 文件中。

# 在ORM模型的save()方法调用之前或之后发送信号:
        django.db.models.signals.pre_save 
        django.db.models.signals.post_save
# 在ORM模型或查询集的delete()方法调用之前或之后发送信号:        
        django.db.models.signals.pre_delete
        django.db.models.signals.post_delete
# 当多对多字段被修改时发送信号:        
        django.db.models.signals.m2m_changed
# 当接收和关闭HTTP请求时发送信号:
        django.core.signals.request_started
        django.core.signals.request_finished
# 规律 : 以 'pre' 开头的 代表动作之前的, 而以 'post' 开头 代表动作之后的

具体 Django 信号内容

定义信号

所有的信号都是django.dispatch.Signal的实例

方法原型:

def __init__(self, providing_args=None, use_caching=False):[source]
    """
    providing_args: 信号提供 给接收者 的参数列表
    use_caching   :是否对于每个不同的发送者缓存发送者所拥有的接收者
    """
    # 注意: 参数可都为空

发送信号

Django中有两种方法用于发送信号。

Signal.send(sender, **kwargs)[source]

Signal.send_robust(sender,** kwargs)[source] 
"""
注意: 1. 必须提供 sender 参数(大部分情况下是一个类名), 表明 发送方的身份
     2.  可以提供任意数量的其他关键字参数
"""

send()和send_robust()返回一个元组对的列表[(receiver, response), ... ],表示接收器和响应值二元元组的列表。

例如: 在视图 函数可定义如下

class Panda(View):
    def get(self,request):
        Signal.send(sender=self.__class__,)        ## 
        return HttpResponse("shiwei is Good")

    def post(self, request):
        Signal.send_robust(sender=self.__class__)  ## 
        return JsonResponse({
            "code": 200,
            'msg': "is Successful",
        })

接收信号

Django 使用 Signal 实例的 connect() 方法用于接收一个指定的信号,

方法原型:

    def connect(self, receiver, sender=None, weak=True, dispatch_uid=None):
        """
        receiver :    当前信号连接的回调函数,也就是处理信号的函数。 
        sender :      指定从哪个发送方接收信号。 
        weak :        是否弱引用
        dispatch_uid :信号接收器的唯一标识符,以防信号多次发送。
        """

注意: 接收信号时 可不指定 信号的发送方 sender 参数,代表 此种信号 都 接收。

第二种 接收信号的 方式为使用 装饰器。 在处理信号的回调函数之上。此种方式内部 也是依次调用每个 信号实例的 connct() 方法 来接收。

方法原型

def receiver(signal, **kwargs):
    def _decorator(func):
        if isinstance(signal, (list, tuple)):   # 第一个 参数 可为信号实例的  元组 或 列表 
            for s in signal:
                s.connect(func, **kwargs)
        else:
            signal.connect(func, **kwargs)
        return func
    return _decorator

信号接收器

所谓 信号接收器 就是 接收到信号之后的触发动作, 一般为一个函数,

def signal_callback(sender, **kwargs):
    print("is my callback")
"""
注意:所有的接收器都必须接收一个sender参数和一个**kwargs通配符参数
"""

防止重复信号

为了防止重复信号,可以设置dispatch_uid参数来标识你的接收器,标识符通常是一个字符串,如下所示

from django.core.signals import request_finished

request_finished.connect(my_callback, dispatch_uid="my_unique_identifier")

最后的结果是,对于每个唯一的dispatch_uid值,你的接收器都只绑定到信号一次

Django 内置信号操作步骤

from django.core.signals import request_finished # 导入 信号

request_finished.connect(callback_func)          # 接收 信号 , 并 指定 回调函数

自定义信号操作步骤

创建文件

Django 定义信号一般都存储于 app 目录下的 signals.py 文件中, 故首先在 app 目录下 创建一个 signals.py 文件

自定义信号

在 第一步定义的 signals.py 中:

from django.dispatch import Signal

suosuo_signal = Signal()

自定义信号接收器

可在任意位置, 一般 放置 与 和在 信号发送语句 同一个 文件中, 例如 视图文件 views.py 中

from django.dispatch import receiver

@receiver(signal=[suosuo_signal,], sender=SuoSuo)  # signal 必须指定,   sender  可选
def basket(sender, **kwargs):                   # 两个 参数必须 同样指定
    print('Signal %s, callback func: basket '%sender.__name__)
    print('SuoSuo 的 信号接收器')

自定义 信号发送语句

例如 在 views.py 中

from django.views import View
from django.http import HttpResponse, JsonResponse
from suosuo.signals import suosuo_signal 

class SuoSuo(View):
    def get(self,request):
        suosuo_signal.send(sender=self.__class__,)
        return HttpResponse("SuoSuo is Good")

    def post(self, request):
        suosuo_signal.send_robust(sender=self.__class__)
        return JsonResponse({
            "code": 200,
            'msg': "is Successful",
        })
posted @ 2019-11-03 01:07  梭梭666  阅读(99)  评论(0编辑  收藏  举报
返回顶部