Django内部包含了一位“信号调度员”:当某事件在框架内发生时,它可以通知到我们的应用程序。 简而言之,当event(事件)发生时,signals(信号)允许若干 senders(寄件人)通知一组 receivers(接收者)。这在我们多个独立的应用代码对同一事件的发生都感兴趣时,特别有用。
django信号(singals)应用范围:
django中singals机制不是异步执行,而是同步执行,所以需要异步执行耗时的任务,不建议使用django自带对的singals。
django signal 对程序的解耦、代码的复用及维护性有很大的帮助。
主要是解耦那些多次重复场合被调用的函数。直接用事件挂钩的方式被调用,这可以让你的代码更干净。
异步任务,可以使用django的channels机制
应用案例:
通知类
通知是signal最常用的场景之一。例如,在论坛中,在帖子得到回复时,通知楼主。从技术上来讲,我们可以将通知逻辑放在回复保存时,但是这并不是一个好的处理方式,这样会时程序耦合度增大,不利于系统的后期扩展维护。如果我们在回复保存时,只发一个简单的信号,外部的通知逻辑拿到信号后,再发送通知,这样回复的逻辑和通知的逻辑做到了分开,后期维护扩展都比较容易。
初始化类
信号的另一个列子便是事件完成后,做一系列的初始化工作。
其他一些使用场景总结
以下情况不要使用signal:
signal与一个model紧密相关,并能移到该model的save()时
signal能使用model manager代替时
signal与一个view紧密相关,并能移到该view中时
以下情况可以使用signal:
signal的receiver需要同时修改对多个model时
将多个app的相同signal引到同一receiver中处理时
在某一model保存之后将cache清除时
无法使用其他方法,但需要一个被调函数来处理某些问题时
django 的 signal 使用可分为2个模块:
signal :signal定义及触发事件
receiver : signal 接受函数
内建signal的使用
django 内部有些定义好的signal供我们使用:
模型相关:
pre_save 对象save前触发
post_save 对象save后触发
pre_delete 对象delete前触发
post_delete 对象delete后触发
m2m_changed ManyToManyField 字段更新后触发
请求相关:
request_started 一个request请求前触发
request_finished request请求后触发
django信号简单使用(django==2.1.1)
1.信号定义
所有信号都是django.core.signals.Singal的实例,providing_args是一个列表,由信号提供监听者的参数名称组成
# 两种引用方式 from django.core.signals import Signal from django.dispatch import Signal # 定义邮件发送信号 email_send = Singal(providing_args=['email'])
2.信号处理函数
from django.dispatch import Signal, receiver # 定义邮件发送信号 email_send = Singal(providing_args=['email']) # 处理函数 @receiver(email_send ) def send_email(sender, **kwargs): """发送邮件处理函数""" print("email_send信号处理函数被调用")
3.信号连接
信号连接就是将信号和处理函数连接起来,信号连接一般是在子应用配置类的ready方法进行操作
class TestAppConfig(object): def ready(self): # 信号连接 email_send.connect(send_email)
4.自定义信号
from django.dispatch import Signal,receiver # 定义邮件发送信号 email_send = Singal(providing_args=['email']) # 处理函数 @receiver(email_send ) def send_email(sender, **kwargs): """发送邮件处理函数""" print("email_send信号处理函数被调用") # 调用信号函数 class Test(Object): """ 其他具体代码""" # 调用邮件发送信号 send_email(sender=self.__class__,username=username)
文档: