利用信号如何监控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之PyUnit单元测试实例
Oct 11 Python
Python发送以整个文件夹的内容为附件的邮件的教程
May 06 Python
详解Python的Django框架中的中间件
Jul 24 Python
Python中扩展包的安装方法详解
Jun 14 Python
Python使用微信SDK实现的微信支付功能示例
Jun 30 Python
一文总结学习Python的14张思维导图
Oct 17 Python
python导入模块交叉引用的方法
Jan 19 Python
在python plt图表中文字大小调节的方法
Jul 08 Python
django之状态保持-使用redis存储session的例子
Jul 28 Python
python使用writerows写csv文件产生多余空行的处理方法
Aug 01 Python
解决python ThreadPoolExecutor 线程池中的异常捕获问题
Apr 08 Python
使用python-cv2实现Harr+Adaboost人脸识别的示例
Oct 27 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
「OVERLORD」动画重要删减!雅儿贝德的背叛?至尊猎杀队结成
2020/04/09 日漫
Memcache 在PHP中的使用技巧
2010/02/08 PHP
php Smarty模板生成html文档的方法
2010/04/12 PHP
php metaphone()函数及php localeconv() 函数实例解析
2016/05/15 PHP
Smarty模板变量调节器用法分析
2016/05/23 PHP
phpstudy2018升级MySQL5.5为5.7教程(图文)
2018/10/24 PHP
来自qq的javascript面试题
2010/07/24 Javascript
得到form下的所有的input的js代码
2013/11/07 Javascript
异步动态加载JS并运行(示例代码)
2013/12/13 Javascript
js实现点击图片将图片地址复制到粘贴板的方法
2015/02/16 Javascript
JavaScript对象反射用法实例
2015/04/17 Javascript
jQ处理xml文件和xml字符串的方法(详解)
2016/11/22 Javascript
jQuery中layer分页器的使用
2017/03/13 Javascript
微信小程序 图片宽度自适应的实现
2017/04/06 Javascript
jquery请求servlet实现ajax异步请求的示例
2017/06/03 jQuery
vue-cli扩展多模块打包的示例代码
2018/04/09 Javascript
微信小程序监听用户登录事件的实现方法
2019/11/11 Javascript
Python实现建立SSH连接的方法
2015/06/03 Python
对Python 简单串口收发GUI界面的实例详解
2019/06/12 Python
matplotlib命令与格式之tick坐标轴日期格式(设置日期主副刻度)
2019/08/06 Python
Python 使用matplotlib模块模拟掷骰子
2019/08/08 Python
pandas 中对特征进行硬编码和onehot编码的实现
2019/12/20 Python
Python with标签使用方法解析
2020/01/17 Python
Python类的绑定方法和非绑定方法实例解析
2020/03/04 Python
联想中国官方商城:Lenovo China
2017/10/18 全球购物
澳洲最大的时尚奢侈品电商平台:Cettire
2020/06/15 全球购物
.net面试题
2015/12/22 面试题
大专生的学习自我评价
2013/12/04 职场文书
个人评价范文分享
2014/01/11 职场文书
排查整治工作方案
2014/06/09 职场文书
小学校长个人总结
2015/03/03 职场文书
外贸采购员岗位职责
2015/04/03 职场文书
离职信范文
2015/06/23 职场文书
2016年师德先进个人事迹材料
2016/02/29 职场文书
java固定大小队列的几种实现方式详解
2021/07/15 Java/Android
node.js使用express-fileupload中间件实现文件上传
2021/07/16 Javascript