【转】使用信号监控 Django 模型对象字段值的变化
转载出处:http://blog.csdn.net/pushiqiang/article/details/74949465
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 )的时候,比较该模型对象的当前的字段值与缓存的字段值,如果不相同则认为该字段值发生了变化。
【转】使用信号监控 Django 模型对象字段值的变化的更多相关文章
- django模型和字段
一个模型(model)就是一个单独的.确定的数据的信息源,包含了数据的字段和操作方法.通常,每个模型映射为一张数据库中的表. 基本的原则如下: 每个模型在Django中的存在形式为一个Python类 ...
- django模型:字段和选项
https://blog.csdn.net/iloveyin/article/details/44852645一.常用字段1.字段类型使用时需要引入django.db.models包,字段类型如下Au ...
- django 模型对象的 update() get_or_create() 的使用
update() 如果一个查询集是一个列表对象, 需要更新该列表对象里所有的单个数据集的数据,可以使用update()方法,而不须遍历整个查询集对象一个个逐一进行修改 obj_list = UserI ...
- Django模型中字段属性choice的使用
根据Django官方文档: from django.db import models class Student(models.Model): FRESHMAN = 'FR' SOPHOMORE = ...
- django模型的字段查询
条件运算符 exact: 查判等 list=BookInfo.objects.filter(id__exact=1) 可简写为: list=BookInfo.objects.filter(id=1) ...
- django 模型增加字段后迁移失败
任 务:已有models.py文件中定义了 ad类(用来描述广告数据库表结构).现在想增加四个新字段:ad_show_type,big_video_url,is_full_screen,vi ...
- Django 模型中字段类型的ImageField
model_pic = models.ImageField(upload_to = 'pic_folder/', default = 'pic_folder/None/no-img.jpg') 参数u ...
- 一个监控oracle数据库某个字段值变化并发送邮件报警的脚本
talk is cheap,here is the code: #!/bin/sh export ORACLE_HOME=/u01/app/oracle/product//client_1/ expo ...
- Django模型之Meta选项详解
Django模型类的Meta是一个内部类,它用于定义一些Django模型类的行为特性.而可用的选项大致包含以下几类 abstract 这个属性是定义当前的模型是不是一个抽象类.所谓抽象类是不会对应数据 ...
随机推荐
- 关于如何用jq定位到某个元素的索引
在点击事件触发时候,通常如果有同样的className的列表我们都需获取它的索引来知道到底点击的是那一个 $('.info_content').mousemove(function(){ var ro ...
- 《超实用的HTML代码段》阅读笔记1——HTML5自动聚焦
在页面加载完成后自动将输入焦点定位到需要的元素,用户就可以直接在改元素中进行输入而不需要手动选择它. 通过autofocus的属性就可以指定这种自动聚焦的功能,示例代码如下: <form nam ...
- JS动态获取项目名以及获取URL地址中的参数
在项目当中我们可能会遇到例如改变的项目名称之后,相对应的地址就需要改变,为了减少工作量,将地址当中的项目名这一块写成动态获取的,那么最关键一点就是我要先获取它,再进行操作: 知识点整理,话不多说,直接 ...
- GCD 使用说明
GCD提供的一些操作队列的方法 名称 说明 dispatch_set_target_queue 将多个队列添加到目标队列中 dispatch_group 将多个队列放入组中,监听所有任务完成状 dis ...
- DrawerLayout Demo
源码下载:http://download.csdn.net/detail/bx276626237/8882763
- 使用 Cosmos DB 创建和查询 NoSQL 表
本教程演示如何使用 Azure 门户创建 Azure Cosmos DB 帐户,然后使用 DocumentDB .NET API 创建具有分区键的文档数据库和集合.通过在创建集合时定义分区键,应用程序 ...
- 洛谷 P1181 数列分段Section I(水题日常)
题目描述 对于给定的一个长度为N的正整数数列A[i],现要将其分成连续的若干段,并且每段和不超过M(可以等于M),问最少能将其分成多少段使得满足要求. 输入输出格式 输入格式: 输入文件divide_ ...
- 如何让Spring MVC显示自定义的404 Not Found页面
不知道大家对千篇一律的404 Not Found的错误页面是否感到腻歪了?其实通过很简单的配置就能够让Spring MVC显示您自定义的404 Not Found错误页面. 在WEB-INF的web. ...
- Java-NestedClass(Interface).
内部类(Nested Class) 内部类:即在一个类中还包含着另外一个类,一般是作为匿名类或者是使用数据隐藏时使用的.例子: //内部类 class Out{ private int age = 1 ...
- 1653: Champion of the Swordsmanship
1653: Champion of the Swordsmanship Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 11 Solved: 8[Subm ...