深入理解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入门教程
Feb 08 Python
python实现对文件中图片生成带标签的txt文件方法
Apr 27 Python
django与小程序实现登录验证功能的示例代码
Feb 19 Python
python使用Plotly绘图工具绘制水平条形图
Mar 25 Python
Python 3 使用Pillow生成漂亮的分形树图片
Dec 24 Python
PyTorch和Keras计算模型参数的例子
Jan 02 Python
基于python监控程序是否关闭
Jan 14 Python
如何在django中实现分页功能
Apr 22 Python
如何快速理解python的垃圾回收机制
Sep 01 Python
python tkinter实现连连看游戏
Nov 16 Python
python 实现表情识别
Nov 21 Python
Python调用高德API实现批量地址转经纬度并写入表格的功能
Jan 12 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+mysql分页代码详解
2008/03/27 PHP
解决ajax+php中文乱码的方法详解
2013/06/09 PHP
php对关联数组循环遍历的实现方法
2015/03/13 PHP
php fseek函数读取大文件两种方法
2016/10/12 PHP
CI框架使用composer安装的依赖包步骤与方法分析
2016/11/21 PHP
javascript学习笔记(三)显示当时时间的代码
2011/04/08 Javascript
window resize和scroll事件的基本优化思路
2014/04/29 Javascript
javascript中call和apply的用法示例分析
2015/04/02 Javascript
DOM 事件的深入浅出(一)
2016/12/05 Javascript
JavaScript实现替换字符串中最后一个字符的方法
2017/03/07 Javascript
Angular.JS中的指令引用template与指令当做属性详解
2017/03/30 Javascript
Angular 2父子组件数据传递之@ViewChild获取子组件详解
2017/07/04 Javascript
高性能的javascript之加载顺序与执行原理篇
2018/01/14 Javascript
electron制作仿制qq聊天界面的示例代码
2018/11/26 Javascript
微信小程序实现随机验证码功能
2018/12/20 Javascript
JavaScript变速动画函数封装添加任意多个属性
2019/04/03 Javascript
JavaScript实现身份证验证代码实例
2019/08/26 Javascript
js+for循环实现字符串自动转义的代码(把后面的字符替换前面的字符)
2020/12/24 Javascript
js canvas实现五子棋小游戏
2021/01/22 Javascript
vue3.0 自适应不同分辨率电脑的操作
2021/02/06 Vue.js
python生成验证码图片代码分享
2016/01/28 Python
详解python发送各类邮件的主要方法
2016/12/22 Python
python实现决策树分类算法
2017/12/21 Python
Python命令行解析模块详解
2018/02/01 Python
python进阶之多线程对同一个全局变量的处理方法
2018/11/09 Python
Python代码实现http/https代理服务器的脚本
2019/08/12 Python
Django错误:TypeError at / 'bool' object is not callable解决
2019/08/16 Python
html2canvas把div保存图片高清图的方法示例
2018/03/05 HTML / CSS
如何设定的weblogic的热启动模式(开发模式)与产品发布模式
2012/09/08 面试题
企划主管岗位职责
2013/12/12 职场文书
品牌宣传方案
2014/03/21 职场文书
爱与责任师德演讲稿
2014/08/26 职场文书
党委书记个人对照检查材料
2014/09/15 职场文书
婚礼迎宾词大全
2015/08/10 职场文书
创业计划书之美容店
2019/09/16 职场文书
微信小程序和php的登录实现
2021/04/01 PHP