利用信号如何监控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的Django框架中模板碎片缓存简介
Jul 24 Python
Python set常用操作函数集锦
Nov 15 Python
Django如何简单快速实现PUT、DELETE方法
Jul 24 Python
Python中最好用的命令行参数解析工具(argparse)
Aug 23 Python
django 多对多表的创建和插入代码实现
Sep 09 Python
Python hashlib模块实例使用详解
Dec 24 Python
Python常用模块sys,os,time,random功能与用法实例分析
Jan 07 Python
python实现简单飞行棋
Feb 06 Python
Python AutoCAD 系统设置的实现方法
Apr 01 Python
python中怎么表示空值
Jun 19 Python
基于python实现MQTT发布订阅过程原理解析
Jul 27 Python
基于Python爬取搜狐证券股票过程解析
Nov 18 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
Yii中CArrayDataProvider和CActiveDataProvider区别实例分析
2016/03/02 PHP
JavaScript类和继承 constructor属性
2010/03/04 Javascript
JQuery中的ready函数冲突的解决方法
2010/05/17 Javascript
jQuery实现HTML表格单元格的合并功能
2016/04/06 Javascript
jQuery使用ajax跨域获取数据的简单实例
2016/05/18 Javascript
JavaScript中的数组遍历forEach()与map()方法以及兼容写法介绍
2016/05/19 Javascript
vue.js入门教程之绑定class和style样式
2016/09/02 Javascript
详解基于Node.js的微信JS-SDK后端接口实现代码
2017/07/15 Javascript
详解vue前后台数据交互vue-resource文档
2017/07/19 Javascript
vue中使用localstorage来存储页面信息
2017/11/04 Javascript
详解webpack自定义loader初探
2018/08/29 Javascript
angularJS自定义directive之带参方法传递详解
2018/10/09 Javascript
js操作table中tr的顺序实现上移下移一行的效果
2018/11/22 Javascript
javascript全局自定义鼠标右键菜单
2020/12/08 Javascript
Nginx搭建HTTPS服务器和强制使用HTTPS访问的方法
2015/08/16 Python
Python的math模块中的常用数学函数整理
2016/02/04 Python
[原创]windows下Anaconda的安装与配置正解(Anaconda入门教程)
2018/04/05 Python
python sys,os,time模块的使用(包括时间格式的各种转换)
2018/04/27 Python
Python中的十大图像处理工具(小结)
2019/06/10 Python
python3.7 openpyxl 删除指定一列或者一行的代码
2019/10/08 Python
Python操作列表常用方法实例小结【创建、遍历、统计、切片等】
2019/10/25 Python
pycharm工具连接mysql数据库失败问题
2020/04/01 Python
Python中Qslider控件实操详解
2021/02/20 Python
澳大利亚药房在线:ThePharmacy
2017/10/04 全球购物
美国学校用品、教室和教学商店:Discount School Supply
2018/04/04 全球购物
Proenza Schouler官方网站:纽约女装和配饰品牌
2019/01/03 全球购物
兰蔻俄罗斯官方网站:Lancome俄罗斯
2019/12/09 全球购物
大学军训感言400字
2014/03/11 职场文书
中职毕业生自我鉴定
2014/09/13 职场文书
圣诞晚会主持词开场白
2015/05/28 职场文书
导游词之鲁迅祖居
2019/10/17 职场文书
python某漫画app逆向
2021/03/31 Python
pytorch 带batch的tensor类型图像显示操作
2021/05/20 Python
正确使用MySQL INSERT INTO语句
2021/05/26 MySQL
一文了解MySQL二级索引的查询过程
2022/02/24 MySQL
使用refresh_token实现无感刷新页面
2022/04/26 Javascript