深入理解Django自定义信号(signals)


Posted in Python onOctober 15, 2018

django中自定义了一些singals,用于监听一些操作,并发出通知

官方解释:

Django 提供一个“信号分发器”,允许解耦的应用在框架的其它地方发生操作时会被通知到。

简单来说,信号允许特定的sender通知一组receiver某些操作已经发生。这在多处代码和同一事件有关联的情况下很有用。
django中已经内置了一些singals,在django/db/models/signal.py中,如

Model signals
  pre_init          # django的modal执行其构造方法前,自动触发
  post_init          # django的modal执行其构造方法后,自动触发
  pre_save          # django的modal对象保存前,自动触发
  post_save          # django的modal对象保存后,自动触发
  pre_delete         # django的modal对象删除前,自动触发
  post_delete         # django的modal对象删除后,自动触发
  m2m_changed         # django的modal中使用m2m字段操作第三张(add,remove,clear)前后,自动触发
  class_prepared       # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
  
Management signals
  pre_migrate         # 执行migrate命令前,自动触发
  post_migrate        # 执行migrate命令后,自动触发
  
Request/response signals
  request_started       # 请求到来前,自动触发
  request_finished      # 请求结束后,自动触发
  got_request_exception    # 请求异常后,自动触发
  
Test signals
  setting_changed       # 使用test测试修改配置文件时,自动触发
  template_rendered      # 使用test测试渲染模板时,自动触发
  
Database Wrappers
  connection_created     # 创建数据库连接时,自动触发

用法:

利用这几个singals可以实现model中的一些联动操作,比如,要想更改通过model更新记录时,记下操作者的日志,可以直接在操作的地方使用post_save装饰器,

或者改写post_save,使其记录相关信息,一劳永逸。或者在request请求时,记录请求信息。

from django.core.signals import request_finished
from django.dispatch import receiver

@receiver(request_finished)
def my_callback(sender, **kwargs):
  print("Request finished!")

如何自定义singals?

a. 定义singal文件

import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

b. 注册singal

def callback(sender, **kwargs):
  print("callback")
  print(sender,kwargs)
  pizza_done.connect(callback)

c. 触发信号

from 路径 import pizza_done
pizza_done.send(sender='seven',toppings=123, size=456)

需求场景:

项目中有一个需求,当model(即库的数据)被修改或者删除时,自动触发一个redis的同步任务(后来发现这个需求没有意义....),model的保存有post_save,删除有post_delete,唯独没有update,而代码中使用update的场景蛮多的,就搜了下为什么就是没有update的singals。

看到:https://code.djangoproject.com/ticket/12184

其实很早就有人给django官方提过这种方式,为什么不在官方版本中添加,具体这个pr为什么没有被接受,可以看下里面的讨论,反正当时的django1.9仍然不支持,只能自己先写一个用用,有问题了再撤掉好了。

解决方式:

singals.py文件

# coding:utf-8
from django.dispatch import Signal
post_update = Signal(providing_args=["user"])

models.py文件

-----------针对某个model,重写其queryset中的update方法-----------

//引入自定义的signal文件
from tools import signals 

class MyCustomQuerySet(models.query.QuerySet):
  def update(self, **kwargs):
    super(MyCustomQuerySet, self).update(**kwargs)
    //update被调用时, 发送该singalsignals
    signals.post_update.send(sender=self.model, user="xxx")
    print("finished!")

class MyCustomManager(models.Manager):
  def get_queryset(self):
    return MyCustomQuerySet(self.model, using=self._db)

class crontab_ping(models.Model):
  name = models.CharField(max_length=64, blank=True, null=True)
  objects = MyCustomManager()

callback.py文件:

-------接收signal,触发操作----------

from tools.signals import post_update

@receiver(post_update)
def post_update_callback(sender, **kwargs):
  print(kwargs['user'])
  print("post_update_success")

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
win7安装python生成随机数代码分享
Dec 27 Python
python切换hosts文件代码示例
Dec 31 Python
Python的类实例属性访问规则探讨
Jan 30 Python
Python中字符串对齐方法介绍
May 21 Python
python的xpath获取div标签内html内容,实现innerhtml功能的方法
Jan 02 Python
Python中的集合介绍
Jan 28 Python
Python读写文件基础知识点
Jun 10 Python
selenium 安装与chromedriver安装的方法步骤
Jun 12 Python
window环境pip切换国内源(pip安装异常缓慢的问题)
Dec 31 Python
python快速安装OpenCV的步骤记录
Feb 22 Python
在 Golang 中实现 Cache::remember 方法详解
Mar 30 Python
Pygame Event事件模块的详细示例
Nov 17 Python
使用numba对Python运算加速的方法
Oct 15 #Python
浅谈解除装饰器作用(python3新增)
Oct 15 #Python
python  创建一个保留重复值的列表的补码
Oct 15 #Python
python 美化输出信息的实例
Oct 15 #Python
python  Django中的apps.py的目的是什么
Oct 15 #Python
使用Python监视指定目录下文件变更的方法
Oct 15 #Python
Python调用adb命令实现对多台设备同时进行reboot的方法
Oct 15 #Python
You might like
无需重新编译php加入ftp扩展的解决方法
2013/02/07 PHP
php实现只保留mysql中最新1000条记录
2015/06/18 PHP
php安全配置记录和常见错误梳理(总结)
2017/03/28 PHP
PHP判断访客是否手机端(移动端浏览器)访问的方法总结【4种方法】
2019/03/27 PHP
TP3.2.3框架文件上传操作实例详解
2020/01/23 PHP
Js 获取当前日期时间及其它操作实现代码
2021/03/04 Javascript
document.compatMode介绍
2009/05/21 Javascript
基于JavaScript实现图片点击弹出窗口而不是保存
2016/02/06 Javascript
快速掌握Node.js之Window下配置NodeJs环境
2016/03/21 NodeJs
js 上传文件预览的简单实例
2016/08/16 Javascript
简单谈谈JS数组中的indexOf方法
2016/10/13 Javascript
JS产生随机数的用法小结
2016/12/10 Javascript
angular学习之ngRoute路由机制
2017/04/12 Javascript
vue生成随机验证码的示例代码
2017/09/29 Javascript
用Vue写一个分页器的示例代码
2018/04/22 Javascript
JS实现省市县三级下拉联动
2020/04/10 Javascript
[03:54]Ehome出征西雅图 回顾2016国际邀请赛晋级之路
2016/08/02 DOTA
[50:28]2018DOTA2亚洲邀请赛 3.31 小组赛 A组 Newbee vs KG
2018/04/01 DOTA
[01:05:56]Liquid vs VP Supermajor决赛 BO 第二场 6.10
2018/07/04 DOTA
跨平台python异步回调机制实现和使用方法
2013/11/26 Python
Python原始字符串(raw strings)用法实例
2014/10/13 Python
简单谈谈Python中函数的可变参数
2016/09/02 Python
在PyCharm下打包*.py程序成.exe的方法
2018/11/29 Python
python dict 相同key 合并value的实例
2019/01/21 Python
Python 使用多属性来进行排序
2019/09/01 Python
python GUI库图形界面开发之PyQt5多线程中信号与槽的详细使用方法与实例
2020/03/08 Python
西海岸男士和男童服装:Johnnie-O
2018/03/15 全球购物
北大青鸟学生求职信
2013/09/24 职场文书
基层党员公开承诺书
2014/05/29 职场文书
企业文化口号
2014/06/12 职场文书
纪念九一八事变演讲稿:牢记九一八,屈辱怎能忘
2014/09/14 职场文书
2014年党建工作总结
2014/11/11 职场文书
万里长城导游词
2015/01/30 职场文书
岳庙导游词
2015/02/04 职场文书
小区环境卫生倡议书
2015/04/29 职场文书
52条SQL语句教你性能优化
2021/05/25 MySQL