3分钟看懂Python后端必须知道的Django的信号机制
作者:画星星高手 发布时间:2022-08-17 18:17:55
概念
django自带一套信号机制来帮助我们在框架的不同位置之间传递信息。也就是说,当某一事件发生时,信号系统可以允许一个或多个发送者(senders)将通知或信号(signals)发送给一组接受者(receivers)。
(感觉就很像Qt的信号与槽机制)
信号系统包含以下三要素:
发送者-信号的发出方
信号-信号本身
接收者-信号的接受者
Django内置了一整套信号,下面是一些比较常用的:
Django内置信号
Model 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类,对于每一个类,自动触发
Management signals
pre_migrate # 执行migrate命令前,自动触发
post_migrate # 执行migrate命令后,自动触发
Request/response signals
request_started # 请求到来前,自动触发
request_finished # 请求结束后,自动触发
got_request_exception # 请求异常后,自动触发
Test signals
setting_changed # 使用test测试修改配置文件时,自动触发
template_rendered # 使用test测试渲染模板时,自动触发
Database Wrappers
connection_created # 创建数据库连接时,自动触发
在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
这就很方便了,想象一下这样一个情景,我们引入了一个第三方的Django库,他会创建模型,我们想要在不修改他的代码的情况下,在他创建模型的时候同时修改其他表的数据,那么这时候信号机制就能派上用场了。
简单使用例子
信号监听有两种方式,一种是 Signal.connect() 方法,一种是装饰器。
Signal.connect()方法
方法原型:
Signal.connect(receiver, sender=None, weak=True, dispatch_uid=None)[source]
参数:
receiver :当前信号连接的回调函数,也就是处理信号的函数。
sender :指定从哪个发送方接收信号。
weak : 是否弱引用
dispatch_uid :信号 * 的唯一标识符,以防信号多次发送。
装饰器法
from django.core.signals import request_finished
from django.dispatch import receiver
@receiver(request_finished)
def my_callback(sender, **kwargs):
print("Request finished!")
可以给 receiver 添加 sender 参数来筛选接收哪个模型产生的信号,比如:
from django.db.models import signals
from django.dispatch import receiver
@receiver(signals.post_save, sender=MyModel)
def demo_callback(sender: MyModel, instance: MyModel, **kwargs):
pass
注意要读取传入的模型对象一定是要用 instance 参数,不是 sender ! sender 是一个类型!
设置dispatch_uid参数防止重复信号
为了防止重复信号,可以设置dispatch_uid参数来标识你的 * ,标识符通常是一个字符串,如下所示:
from django.core.signals import request_finished
request_finished.connect(my_callback, dispatch_uid="my_unique_identifier")
断开信号
在满足某些条件下,我们不再需要监听信号,可以选择断开信号。
Signal.disconnect()用来断开信号的 * 。和Signal.connect()中的参数相同。如果 * 成功断开,返回True,否则返回False。
Signal.disconnect(receiver=None, sender=None, dispatch_uid=None)[source]
后记
最近刚入职项目很多特别的忙,也学到了很多新技术,但是感觉已经好久没有时间来好好写一篇博客了,就算是本文也是短时间拼凑的,真是难呀,周末得好好整理一下最近的技术笔记。
关于Django信号机制的更多内容(自定义信号等),可以参考官方文档。 https://docs.djangoproject.com/en/3.0/topics/signals/
来源:https://www.cnblogs.com/deali/p/13372922.html


猜你喜欢
- ADO也提供更有效率方法来取得数据。GetRows 方法传回一个二维的数组变量,每一行对应Recordset中的一笔记录,且每
- 最近做的一个项目对日期时间的处理比较多,最后整理到一个工具类里面,方便以后使用:1. 在utils文件夹下新建一个dateTimeUtil.
- golang的字符有如下两种:一种是 uint8['ju:nɪt] 类型叫做 byte 型,代表了 ASCII 码的一个字符。另一种
- jQuery.sheet 是一个用于创建 Web 电子表格的 jQuery插件,其功能及界面风格和微软的 Excel 非常相似,使得用户不至
- # set 不支持索引和切片,是一个无需的不重复得到容器# 类似于字典,但是只有key 没有value# 创建集合dic1={}set1={
- js给span标签赋值的方法?一般有两种方法:第一种方法:输出html<body onload="s()">
- 一.windows系统的解决方法1.首先以系统管理员身份登陆系统。2.停止MySQL的服务。3.进入命令窗口,然后进入MySQL的安装目录,
- Numpy随机矩阵: np.random.randn(d0, d1, d2, ...)矩阵大小与形状: np.ndarray.size 与
- 让我们重温一下JavaScript的一些基础知识,请先写出以下代码中问号处的答案,再运行比较!<script type=&q
- 比如:现需要向学生表中插入新的学生数据。但在插入学生数据的时,需要同时检查老师表里的数据。如果插入学生的老师不在老师表里,则先向老师表中插入
- 介绍OpenCV 是一个很好的处理图像和视频的工具。无论你是想让你的照片呈现 90 年代的黑白效果,还是执行复杂的数学运算,OpenCV 都
- 本人电脑上的Python为3.5,安装在Windows上,虽然安装过程中选择了pip,但是在命令行输入pip后仍然不能成功,尝试一下方法,终
- 大概五年前吧,我那时还在为一家约会网站做开发工作。他们是早期创业公司,但他们也开始拥有了一些稳定用户量。不像其他约会网站,这家公司向来以洁身
- 说明:操作系统:Windows Server 2003MySQL版本:5.5.25MySQL程序安装目录:D:\Program Files\
- 曾经为看别人写的杂乱代码而头痛吗?曾经为看BWindow代码而烦恼吗?曾经为减小JS体积和JS的可读性之间的矛盾而左右徘徊吗?最好的办法是有
- @StartIndex为当前页起始序号,@EndIndex为当前页结束记录序号,可以直接作为参数输入,也可以通过输入PageSize和Pag
- 最近有一个小项目,有如下的需求:将某几个源码文件夹进行打包,文件夹内有py文件、dll文件、exe文件等各种文件类型打包生成的安装包,在进行
- 前言你的心要如溪水般柔软,你的眼波要像春天般明媚。 ——余光中似乎很少看见湍急的溪流,多数
- OUTLINE 常见的时间字符串与timestamp之间的转换日期与timestamp之间的转换常见的时间字符串与timesta
- 在找寻材料的时候,会看到一些暂时用不到但是内容不错的网页,就这样关闭未免浪费掉了,下次也不一定能再次搜索到。有些小伙伴会提出可以保存网页链接