利用信号如何监控Django模型对象字段值的变化详解
django信号系统
django自带一套信号发射系统来帮助我们在框架的不同位置传递信息.也就是说,当某一事件发生时,信号系统可以允许一个或多个发送者(senders)将通知或信号(signals)推送给一组接受者(receivers).信号系统在我们多处代码与同一个事件相关是特别有用.
既然是信号系统,那么必须包含以下要素:
1.发送者-谁发送了信号
2.信号-发送的信号本身
3.接收者-信号是发给谁的
Django信号(Signals)的功能类似于WordPress的动作(action),用于为项目全局增加事件的广播(dispatch)与接收(receive)机制。其中,灵活使用其内置的模型信号(ModelSignals)的接收功能就可以监控大部分模型对象(Modelinstances)的变化。因为不需要修改模型本身的代码,在进行跨应用(App)监控时有低耦合的优势。
基本用法
信号的基本用法官方文档上的主题与参考上已经有详细描述。本文只提几个要点(本文环境:Django1.8&Python3.4):
代码组织
官方推荐在应用目录下新增一个signals.py文件,同时参考官方文档的应用配置节中自定义应用配置(AppConfig),重载应用配置类的run方法,在该方法内调用from.importsignals
接收信号
推荐使用django.dispatch.receiver这个装饰器进行信号的接收:
fromdjango.db.modelsimportsignals fromdjango.dispatchimportreceiver fromstudents.modelsimportStudent from.modelsimportAnnouncement @receiver(signals.post_save,sender=Student) defwelcome_student(instance,created,**kwargs): ifcreated: Announcement.objects.create(content='Welcomenewstudent'+instance.name)
从代码可读性的角度来讲,建议一个接收函数只做一件事。
监控特定字段(field)值的变化
从上一段代码可以知道,通过接收模型post_save信号,可以得知发生了保存模型对象的操作,并且还可以区分出是创建了模型对象还是更新了模型对象。然而,模型信号并没有提供针对特定字段值变化的广播功能,虽然该信号提供了update_fields参数,但是并不能证明在该参数中的字段名的字段值一定发生了变化,所以我们要采用一个结合post_init信号的变通方法。
举一个例子:当学生名字发生改变之后发布一条公告。
fromdjango.db.modelsimportsignals fromdjango.dispatchimportreceiver fromstudents.modelsimportStudent from.modelsimportAnnouncement @receiver(signals.post_init,sender=Student) defwelcome_student(instance,**kwargs): instance.__original_name=instance.name @receiver(signals.post_save,sender=Student) defwelcome_student(instance,created,**kwargs): ifnotcreatedandinstance.__original_name!=instance.name: Announcement.objects.create(content= 'Student%shasrenamedto%s'%(instance.__original_name,instance.name))
简单的说就是在该模型广播post_init信号的时候,在模型对象中缓存当前的字段值;在模型广播post_save(或pre_save)的时候,比较该模型对象的当前的字段值与缓存的字段值,如果不相同则认为该字段值发生了变化。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。