利用信号如何监控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的类实例属性访问规则探讨
Jan 30 Python
使用C#配合ArcGIS Engine进行地理信息系统开发
Feb 19 Python
python素数筛选法浅析
Mar 19 Python
Python爬虫基础之XPath语法与lxml库的用法详解
Sep 13 Python
python自定义函数实现最大值的输出方法
Jul 09 Python
python中的RSA加密与解密实例解析
Nov 18 Python
selenium中get_cookies()和add_cookie()的用法详解
Jan 06 Python
python GUI库图形界面开发之PyQt5中QWebEngineView内嵌网页与Python的数据交互传参详细方法实例
Feb 26 Python
Python 操作 MySQL数据库
Sep 18 Python
python 对象真假值的实例(哪些视为False)
Dec 11 Python
pip 20.3 新版本发布!即将抛弃 Python 2.x(推荐)
Dec 16 Python
Pandas-DataFrame知识点汇总
Mar 16 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
由php的call_user_func传reference引发的思考
2010/07/23 PHP
php数组函数序列之each() - 获取数组当前内部指针所指向元素的键名和键值,并将指针移到下一位
2011/10/31 PHP
基于PHP常用字符串的总结(待续)
2013/06/07 PHP
PHP引用符&的用法详细解析
2013/08/22 PHP
PHP中使用file_get_contents post数据代码例子
2015/02/13 PHP
PHP翻页跳转功能实现方法
2020/11/30 PHP
PHP 的Opcache加速的使用方法
2017/12/29 PHP
在js中单选框和复选框获取值的方式
2009/11/06 Javascript
js与运算符和或运算符的妙用
2014/02/14 Javascript
js关于命名空间的函数实例
2015/02/05 Javascript
详解JavaScript逻辑Not运算符
2015/12/04 Javascript
JavaScript拖拽、碰撞、重力及弹性运动实例分析
2016/01/08 Javascript
三种AngularJS中获取数据源的方式
2016/02/02 Javascript
JavaScript 数组some()和filter()的用法及区别
2016/05/20 Javascript
jQuery中事件与动画的总结分享
2016/05/24 Javascript
AngularJs Scope详解及示例代码
2016/09/01 Javascript
Angularjs 设置全局变量的方法总结
2016/10/20 Javascript
Vue-Router实现页面正在加载特效方法示例
2017/02/12 Javascript
AngularJS实现自定义指令与控制器数据交互的方法示例
2017/06/19 Javascript
基于vue的换肤功能的示例代码
2017/10/10 Javascript
基于Node.js实现压缩和解压缩的方法
2018/02/13 Javascript
vue mounted 调用两次的完美解决办法
2018/10/29 Javascript
vue实现todolist功能、todolist组件拆分及todolist的删除功能
2019/04/11 Javascript
使用python装饰器验证配置文件示例
2014/02/24 Python
python编写暴力破解FTP密码小工具
2014/11/19 Python
介绍Python的@property装饰器的用法
2015/04/28 Python
Python3实现的判断回文链表算法示例
2019/03/08 Python
Python缓存技术实现过程详解
2019/09/25 Python
django API 中接口的互相调用实例
2020/04/01 Python
学会python自动收发邮件 代替你问候女友
2020/05/20 Python
英国口碑最好的的维他命胶囊品牌:Myvitamins(有中文站)
2016/12/03 全球购物
美国领先的眼镜和太阳镜在线零售商:Glasses.com
2019/08/26 全球购物
数控机床专业自荐信
2014/05/19 职场文书
家庭贫困证明
2015/06/16 职场文书
社区志愿服务活动感想
2015/08/07 职场文书
Python tensorflow卷积神经Inception V3网络结构
2022/05/06 Python