深入理解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中使用urllib2获取http请求状态码的代码例子
Jul 07 Python
python+opencv实现的简单人脸识别代码示例
Nov 14 Python
浅谈Python中range和xrange的区别
Dec 20 Python
Python实现简单生成验证码功能【基于random模块】
Feb 10 Python
Python 迭代,for...in遍历,迭代原理与应用示例
Oct 12 Python
Python实现隐马尔可夫模型的前向后向算法的示例代码
Dec 31 Python
python游戏开发的五个案例分享
Mar 09 Python
Python3创建Django项目的几种方法(3种)
Jun 03 Python
python 8种必备的gui库
Aug 27 Python
Python 实现国产SM3加密算法的示例代码
Sep 21 Python
PyCharm配置KBEngine快速处理代码提示冲突、配置命令问题
Apr 03 Python
分享几种python 变量合并方法
Mar 20 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 数据库字段复用的基本原理与示例
2011/07/22 PHP
php5.3提示Function ereg() is deprecated Error问题解决方法
2014/11/12 PHP
php验证邮箱和ip地址最简单方法汇总
2015/10/30 PHP
PHP使用curl函数发送Post请求的注意事项
2016/11/26 PHP
php大小写转换函数(strtolower、strtoupper)用法介绍
2017/11/17 PHP
PHP折半(二分)查找算法实例分析
2018/05/12 PHP
jQuery 解析xml文件
2009/08/09 Javascript
JavaScript 基础篇之运算符、语句(二)
2012/04/07 Javascript
js根据给定的日期计算当月有多少天实现思路及代码
2013/02/25 Javascript
解析window.open的使用方法总结
2013/06/19 Javascript
复制js对象方法(详解)
2013/07/08 Javascript
JavaScript实现的日期控件具体代码
2013/11/18 Javascript
jQuery中:last选择器用法实例
2014/12/30 Javascript
JQuery对ASP.NET MVC数据进行更新删除
2016/07/13 Javascript
AngularJS基础 ng-list 指令详解及示例代码
2016/08/02 Javascript
分类解析jQuery选择器
2016/11/23 Javascript
JS中Safari浏览器中的Date
2017/07/17 Javascript
微信小程序时间戳转日期的详解
2019/04/30 Javascript
[01:31:03]DOTA2完美盛典全回顾 见证十五项大奖花落谁家
2017/11/28 DOTA
Python中bisect的用法
2014/09/23 Python
把MySQL表结构映射为Python中的对象的教程
2015/04/07 Python
Python对list列表结构中的值进行去重的方法总结
2016/05/07 Python
python利用matplotlib库绘制饼图的方法示例
2016/12/18 Python
Python处理PDF及生成多层PDF实例代码
2017/04/24 Python
利用python如何处理百万条数据(适用java新手)
2018/06/06 Python
Python unittest 简单实现参数化的方法
2018/11/30 Python
通过PHP与Python代码对比的语法差异详解
2019/07/10 Python
HTML5实现一个能够移动的小坦克示例代码
2013/09/02 HTML / CSS
HTML5 Blob 实现文件下载功能的示例代码
2019/11/29 HTML / CSS
编写一个类体现构造,公有,私有方法,静态,私有变量
2013/08/10 面试题
中专生职业生涯规划书范文
2014/01/10 职场文书
2014新年元旦活动策划方案
2014/02/18 职场文书
复兴之路展览观后感
2015/06/02 职场文书
《钢铁是怎样炼成的》高中读后感
2019/08/07 职场文书
如何用PHP实现多线程编程
2021/05/26 PHP
html+css实现滚动到元素位置显示加载动画效果
2021/08/02 HTML / CSS