深入理解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解析xml文件实例分析
May 27 Python
详解Python装饰器由浅入深
Dec 09 Python
python文件名和文件路径操作实例
Sep 29 Python
python正则表达式去除两个特殊字符间的内容方法
Dec 24 Python
Python中类的创建和实例化操作示例
Feb 27 Python
pyqt弹出新对话框,以及关闭对话框获取数据的实例
Jun 18 Python
Python树莓派学习笔记之UDP传输视频帧操作详解
Nov 15 Python
Python 面向对象静态方法、类方法、属性方法知识点小结
Mar 09 Python
Django User 模块之 AbstractUser 扩展详解
Mar 11 Python
Python流程控制语句的深入讲解
Jun 15 Python
vue.js刷新当前页面的实例讲解
Dec 29 Python
Python Matplotlib绘制两个Y轴图像
Apr 13 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基础知识:控制结构
2006/12/13 PHP
php文件打包 下载之使用PHP自带的ZipArchive压缩文件并下载打包好的文件
2012/06/13 PHP
CI框架在CLI下执行占用内存过大问题的解决方法
2014/06/17 PHP
JavaScript 异步调用框架 (Part 2 - 用例设计)
2009/08/03 Javascript
JavaScript使用HTML5的window.postMessage实现跨域通信例子
2014/04/11 Javascript
用html5 js实现点击一个按钮达到浏览器全屏效果
2014/05/28 Javascript
jQuery中andSelf()方法用法实例
2015/01/08 Javascript
浅谈使用MVC模式进行JavaScript程序开发
2015/11/10 Javascript
jQuery-1.9.1源码分析系列(十一)DOM操作续之克隆节点
2015/12/01 Javascript
BootStrap初学者对弹出框和进度条的使用感觉
2016/06/27 Javascript
使用JavaScriptCore实现OC和JS交互详解
2017/03/28 Javascript
详解angularJS自定义指令间的相互交互
2017/07/05 Javascript
Vue不能检测到Object/Array更新的情况的解决
2018/06/26 Javascript
AngularJS 事件发布机制
2018/08/28 Javascript
详解async/await 异步应用的常用场景
2019/05/13 Javascript
浅析Vue下的components模板使用及应用
2019/11/27 Javascript
django进阶之cookie和session的使用示例
2018/08/17 Python
Python使用装饰器模拟用户登陆验证功能示例
2018/08/24 Python
python Django 创建应用过程图示详解
2019/07/29 Python
Laravel框架表单验证格式化输出的方法
2019/09/25 Python
pandas读取csv文件提示不存在的解决方法及原因分析
2020/04/21 Python
详解python的变量缓存机制
2021/01/24 Python
Martinelli官方商店:西班牙皮鞋和高跟鞋品牌
2019/07/30 全球购物
GAZMAN官网:澳大利亚领先的男装品牌
2019/12/19 全球购物
物业管理个人自我评价
2013/11/08 职场文书
仓库班组长岗位职责
2013/12/12 职场文书
大学军训感言800字
2014/02/27 职场文书
新兵入伍心得体会
2014/09/04 职场文书
高温慰问简报
2015/07/21 职场文书
企业宣传稿范文
2015/07/23 职场文书
八年级数学教学反思
2016/02/17 职场文书
少年的你:世界上没有如果,要在第一次就勇敢的反抗
2019/11/20 职场文书
教你解决往mysql数据库中存入汉字报错的方法
2021/05/06 MySQL
vscode中使用npm安装babel的方法
2021/08/02 Javascript
Canvas如何做个雪花屏版404的实现
2021/09/25 HTML / CSS
Python经常使用的一些内置函数
2022/04/11 Python