3分钟看懂Python后端必须知道的Django的信号机制


Posted in Python onJuly 26, 2020

概念

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/

到此这篇关于3分钟看懂Python后端必须知道的Django的信号机制的文章就介绍到这了,更多相关Django 信号机制内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python实现比较两个列表(list)范围
Jun 12 Python
Django中对通过测试的用户进行限制访问的方法
Jul 23 Python
轻松理解Python 中的 descriptor
Sep 15 Python
python通过opencv实现批量剪切图片
Nov 13 Python
python requests.post带head和body的实例
Jan 02 Python
Python3.5面向对象编程图文与实例详解
Apr 24 Python
python 判断文件还是文件夹的简单实例
Jun 10 Python
Python3 ID3决策树判断申请贷款是否成功的实现代码
May 21 Python
Python -m参数原理及使用方法解析
Aug 21 Python
pycharm中选中一个单词替换所有重复单词的实现方法
Nov 17 Python
[原创]赚疯了!转手立赚800+?大佬的python「抢茅台脚本」使用教程
Jan 12 Python
OpenCV-Python实现人脸磨皮算法
Jun 07 Python
给Django Admin添加验证码和多次登录尝试限制的实现
Jul 26 #Python
python如何支持并发方法详解
Jul 25 #Python
Python获取浏览器窗口句柄过程解析
Jul 25 #Python
用Python 爬取猫眼电影数据分析《无名之辈》
Jul 24 #Python
基于Python实现简单学生管理系统
Jul 24 #Python
用python实现学生管理系统
Jul 24 #Python
Python 解析简单的XML数据
Jul 24 #Python
You might like
在“咖啡之国”感受咖啡文化
2021/03/03 咖啡文化
NO3第三帝国留言簿制作过程
2006/10/09 PHP
Yii框架getter与setter方法功能与用法分析
2019/10/22 PHP
JavaScript Event学习第二章 Event浏览器兼容性
2010/02/07 Javascript
Jquery Select操作方法集合脚本之家特别版
2010/05/17 Javascript
密码强度检测效果实现原理与代码
2013/01/04 Javascript
JavaScript异步编程:异步数据收集的具体方法
2013/08/19 Javascript
鼠标移入移出事件改变图片的分辨率的两种方法
2013/12/17 Javascript
javascript实现表格排序 编辑 拖拽 缩放
2015/01/02 Javascript
JS实现简单的键盘打字的效果
2015/04/24 Javascript
JavaScript函数节流概念与用法实例详解
2016/06/20 Javascript
JavaScript中闭包之浅析解读(必看篇)
2016/08/25 Javascript
Javascript中构造函数要注意的一些坑
2017/01/23 Javascript
ie下js不执行的几种可能
2017/02/28 Javascript
vue下跨域设置的相关介绍
2017/08/26 Javascript
微信小程序wx.uploadfile 本地文件转base64的实现代码
2018/06/28 Javascript
js+SVG实现动态时钟效果
2018/07/14 Javascript
angularJs中orderBy筛选以及filter过滤数据的方法
2018/09/30 Javascript
深入理解vue-class-component源码阅读
2019/02/18 Javascript
vue cli 3.x 项目部署到 github pages的方法
2019/04/17 Javascript
[01:03:22]LGD vs OG 2018国际邀请赛淘汰赛BO3 第一场 8.25
2018/08/29 DOTA
python实现的登陆Discuz!论坛通用代码分享
2014/07/11 Python
Python实现获取照片拍摄日期并重命名的方法
2017/09/30 Python
Python中文件的写入读取以及附加文字方法
2019/01/23 Python
python安装numpy和pandas的方法步骤
2019/05/27 Python
详解利用Python scipy.signal.filtfilt() 实现信号滤波
2019/06/05 Python
Python+pyplot绘制带文本标注的柱状图方法
2019/07/08 Python
浅谈python多线程和多线程变量共享问题介绍
2020/04/17 Python
Pyside2中嵌入Matplotlib的绘图的实现
2021/02/22 Python
外包公司软件测试工程师
2014/11/01 面试题
高中毕业生生活的自我评价
2013/12/08 职场文书
人民调解员培训方案
2014/06/05 职场文书
入党积极分子自我批评思想汇报
2014/10/10 职场文书
2014年财务工作总结与计划
2014/12/08 职场文书
2014年政务公开工作总结
2014/12/09 职场文书
2015年信息化建设工作总结
2015/07/23 职场文书