利用信号如何监控Django模型对象字段值的变化详解


Posted in Python onNovember 27, 2017

django信号系统

django自带一套信号发射系统来帮助我们在框架的不同位置传递信息.也就是说,当某一事件发生时,信号系统可以允许一个或多个发送者(senders)将通知或信号(signals)推送给一组接受者(receivers).信号系统在我们多处代码与同一个事件相关是特别有用.

既然是信号系统,那么必须包含以下要素:

 1. 发送者-谁发送了信号

 2. 信号-发送的信号本身

 3. 接收者-信号是发给谁的

Django 信号 (Signals) 的功能类似于 WordPress 的动作 (action),用于为项目全局增加事件的广播 (dispatch) 与接收 (receive) 机制。其中,灵活使用其内置的模型信号 (Model Signals) 的接收功能就可以监控大部分模型对象 (Model instances) 的变化。因为不需要修改模型本身的代码,在进行跨应用 (App) 监控时有低耦合的优势。

基本用法

信号的基本用法官方文档上的 主题 与 参考 上已经有详细描述。本文只提几个要点(本文环境:Django 1.8 & Python 3.4):

代码组织

官方推荐在应用目录下新增一个 signals.py 文件,同时参考官方文档的 应用配置 节中自定义应用配置 (AppConfig) ,重载应用配置类的 run 方法,在该方法内调用 from . import signals

接收信号

推荐使用 django.dispatch.receiver 这个装饰器进行信号的接收:

from django.db.models import signals
from django.dispatch import receiver

from students.models import Student
from .models import Announcement

@receiver(signals.post_save, sender=Student)
def welcome_student(instance, created, **kwargs):
 if created:
  Announcement.objects.create(content='Welcome new student ' + instance.name)

从代码可读性的角度来讲,建议一个接收函数只做一件事。

监控特定字段 (field) 值的变化

从上一段代码可以知道,通过接收模型 post_save 信号,可以得知发生了保存模型对象的操作,并且还可以区分出是创建了模型对象还是更新了模型对象。然而,模型信号并没有提供针对特定字段值变化的广播功能,虽然该信号提供了 update_fields 参数,但是并不能证明在该参数中的字段名的字段值一定发生了变化,所以我们要采用一个结合 post_init 信号的变通方法。

举一个例子:当学生名字发生改变之后发布一条公告。

from django.db.models import signals
from django.dispatch import receiver

from students.models import Student
from .models import Announcement

@receiver(signals.post_init, sender=Student)
def welcome_student(instance, **kwargs):
 instance.__original_name = instance.name

@receiver(signals.post_save, sender=Student)
def welcome_student(instance, created, **kwargs):
 if not created and instance.__original_name != instance.name:
  Announcement.objects.create(content=
   'Student %s has renamed to %s' % (instance.__original_name, instance.name))

简单的说就是在该模型广播 post_init 信号的时候,在模型对象中缓存当前的字段值;在模型广播 post_save (或 pre_save )的时候,比较该模型对象的当前的字段值与缓存的字段值,如果不相同则认为该字段值发生了变化。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。  

Python 相关文章推荐
python实现将pvr格式转换成pvr.ccz的方法
Apr 28 Python
批处理与python代码混合编程的方法
May 19 Python
Python爬取网易云音乐上评论火爆的歌曲
Jan 19 Python
python ansible服务及剧本编写
Dec 29 Python
Python实现查找最小的k个数示例【两种解法】
Jan 08 Python
Python代码生成视频的缩略图的实例讲解
Dec 22 Python
设置jupyter中DataFrame的显示限制方式
Apr 12 Python
Python同时处理多个异常的方法
Jul 28 Python
python中pathlib模块的基本用法与总结
Aug 17 Python
matplotlib实现数据实时刷新的示例代码
Jan 05 Python
基于注解实现 SpringBoot 接口防刷的方法
Mar 02 Python
python实现剪贴板的操作
Jul 01 Python
深入理解Python中range和xrange的区别
Nov 26 #Python
PyCharm在win10的64位系统安装实例
Nov 26 #Python
python shell根据ip获取主机名代码示例
Nov 25 #Python
python自动裁剪图像代码分享
Nov 25 #Python
分享一个简单的python读写文件脚本
Nov 25 #Python
python之virtualenv的简单使用方法(必看篇)
Nov 25 #Python
python多进程实现进程间通信实例
Nov 24 #Python
You might like
第十四节--命名空间
2006/11/16 PHP
PHP error_log()将错误信息写入一个文件(定义和用法)
2013/10/25 PHP
你可能不知道PHP get_meta_tags()函数
2014/05/12 PHP
PHP ADODB实现分页功能简单示例
2018/05/25 PHP
使用jscript实现二进制读写脚本代码
2008/06/09 Javascript
JavaScript Array扩展实现代码
2009/10/14 Javascript
js禁止回车提交表单的示例代码
2013/12/23 Javascript
jquery Ajax 实现加载数据前动画效果的示例代码
2014/02/07 Javascript
如何改进javascript代码的性能
2015/04/02 Javascript
jQuery里filter()函数与find()函数用法分析
2015/06/24 Javascript
JavaScript编写连连看小游戏
2015/07/07 Javascript
微信小程序中hidden不生效原因的解决办法
2017/04/26 Javascript
详解nodejs微信jssdk后端接口
2017/05/25 NodeJs
nodejs更改项目端口号的方法
2018/05/13 NodeJs
Vue+Express实现登录状态权限验证的示例代码
2019/05/05 Javascript
JS替换字符串中指定位置的字符(多种方法)
2020/05/28 Javascript
详解React路由传参方法汇总记录
2020/11/29 Javascript
实例讲解Python设计模式编程之工厂方法模式的使用
2016/03/02 Python
python修改txt文件中的某一项方法
2018/12/29 Python
Python 利用切片从列表中取出一部分使用的方法
2019/02/01 Python
Python中使用双下划线防止类属性被覆盖问题
2019/06/27 Python
Python3 使用pillow库生成随机验证码
2019/08/26 Python
python循环输出三角形图案的例子
2019/11/22 Python
AmazeUi Tree(树形结构) 应用小结
2020/08/17 HTML / CSS
乐高官方旗舰店:LEGO积木玩具
2019/04/06 全球购物
世界上最大的字体市场:MyFonts
2020/01/10 全球购物
校园门卫岗位职责
2013/12/09 职场文书
分厂厂长岗位职责
2013/12/29 职场文书
文科教师毕业的自我评价
2014/01/16 职场文书
标准化管理实施方案
2014/02/25 职场文书
安全教育实施方案
2014/03/02 职场文书
高中课程设置方案
2014/05/28 职场文书
解放思想演讲稿
2014/09/11 职场文书
乡镇群众路线整改落实情况汇报
2014/10/28 职场文书
儿子满月酒致辞
2015/07/29 职场文书
Python使用Kubernetes API访问集群
2021/05/30 Python