深入理解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 相关文章推荐
python操作日期和时间的方法
Mar 11 Python
Python实现把utf-8格式的文件转换成gbk格式的文件
Jan 22 Python
Python进阶_关于命名空间与作用域(详解)
May 29 Python
Python实现将sqlite数据库导出转成Excel(xls)表的方法
Jul 17 Python
python删除过期log文件操作实例解析
Jan 31 Python
python中的json总结
Oct 11 Python
python生成器与迭代器详解
Jan 01 Python
Python参数传递对象的引用原理解析
May 22 Python
使用Keras预训练模型ResNet50进行图像分类方式
May 23 Python
Python 如何展开嵌套的序列
Aug 01 Python
解决pytorch读取自制数据集出现过的问题
May 31 Python
Python绘制散乱的点构成的图的方法
Apr 21 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
十大催泪虐心动漫电影,有几部你还没看
2020/03/04 日漫
php基于str_pad实现卡号不足位数自动补0的方法
2014/11/12 PHP
THINKPHP2.0到3.0有哪些改进之处
2015/01/04 PHP
laravel5环境隐藏index.php后缀(apache)的方法
2019/10/12 PHP
php的RSA加密解密算法原理与用法分析
2020/01/23 PHP
一个JS的日期格式化算法示例
2013/07/31 Javascript
JS和JQUERY获取页面大小,滚动条位置,元素位置(示例代码)
2013/12/14 Javascript
JavaScript严格模式禁用With语句的原因
2014/10/20 Javascript
javascript常用函数归纳整理
2014/10/31 Javascript
jquery插件bootstrapValidator表单验证详解
2016/12/15 Javascript
JQ中$(window).load和$(document).ready区别与执行顺序
2017/03/01 Javascript
简单谈谈React中的路由系统
2017/07/25 Javascript
JS沙箱模式实例分析
2017/09/04 Javascript
vue在使用ECharts时的异步更新和数据加载详解
2017/11/22 Javascript
js实现跟随鼠标移动的小球
2019/08/26 Javascript
layui prompt 设置允许空白提交的方法
2019/09/24 Javascript
Python牛刀小试密码爆破
2011/02/03 Python
Swift中的协议(protocol)学习教程
2016/07/08 Python
使用python和Django完成博客数据库的迁移方法
2018/01/05 Python
python 与服务器的共享文件夹交互方法
2018/12/27 Python
Python常见的pandas用法demo示例
2019/03/16 Python
python绘制已知点的坐标的直线实例
2019/07/04 Python
np.newaxis 实现为 numpy.ndarray(多维数组)增加一个轴
2019/11/30 Python
在TensorFlow中屏蔽warning的方式
2020/02/04 Python
Python pytesseract验证码识别库用法解析
2020/06/29 Python
利用python下载scihub成文献为PDF操作
2020/07/09 Python
Lou & Grey美国官网:主打舒适性面料服饰
2017/12/21 全球购物
Nike香港官网:Nike HK
2019/03/23 全球购物
四川internet信息高速公路(C#)笔试题
2012/02/29 面试题
实习医生自我评价
2013/09/22 职场文书
军训心得体会
2013/12/31 职场文书
离婚协议书范本2014
2014/10/27 职场文书
村党的群众路线教育实践活动总结材料
2014/10/31 职场文书
小学教学工作总结2015
2015/05/13 职场文书
Vue全家桶入门基础教程
2021/05/14 Vue.js
python实现MD5进行文件去重的示例代码
2021/07/09 Python