目录
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", })