深入理解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 19 Python
Python wxPython库使用wx.ListBox创建列表框示例
Sep 03 Python
Python基于datetime或time模块分别获取当前时间戳的方法实例
Feb 19 Python
Python Excel处理库openpyxl使用详解
May 09 Python
浅谈pyqt5在QMainWindow中布局的问题
Jun 21 Python
Python学习笔记之函数的参数和返回值的使用
Nov 20 Python
PyTorch 解决Dataset和Dataloader遇到的问题
Jan 08 Python
Python开发之身份证验证库id_validator验证身份证号合法性及根据身份证号返回住址年龄等信息
Mar 20 Python
Python tornado上传文件的功能
Mar 26 Python
通过实例简单了解Python sys.argv[]使用方法
Aug 04 Python
详解python的变量缓存机制
Jan 24 Python
python疲劳驾驶困倦低头检测功能的实现
Apr 04 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
用Socket发送电子邮件(利用需要验证的SMTP服务器)
2006/10/09 PHP
手把手教你使用DedeCms V3的在线采集图文教程
2007/04/03 PHP
学习php开源项目的源码指南
2014/12/21 PHP
php制作的简单验证码识别代码
2016/01/26 PHP
PHP数据库操作四:mongodb用法分析
2017/08/16 PHP
让getElementsByName适应IE和firefox的方法
2007/09/24 Javascript
JS 添加网页桌面快捷方式的代码详细整理
2012/12/27 Javascript
jquery获取div宽度的实现思路与代码
2013/01/13 Javascript
JS获取下拉列表所选中的TEXT和Value的实现代码
2014/01/11 Javascript
jquery实现可自动收缩的TAB网页选项卡代码
2015/09/06 Javascript
JavaScript拖拽、碰撞、重力及弹性运动实例分析
2016/01/08 Javascript
Bootstrap 实现查询的完美方法
2016/10/26 Javascript
Vue实现购物车功能
2017/04/27 Javascript
AngularJs+Bootstrap实现漂亮的计算器
2017/08/10 Javascript
Vue2仿淘宝实现省市区三级联动
2020/04/15 Javascript
浅谈vue方法内的方法使用this的问题
2018/09/15 Javascript
Webpack 4如何动态切割JS注入文件名详解
2019/07/09 Javascript
Vue解析带html标签的字符串为dom的实例
2019/11/13 Javascript
原生JS利用transform实现banner的无限滚动示例代码
2020/06/15 Javascript
Python操作sqlite3快速、安全插入数据(防注入)的实例
2014/04/26 Python
python实现求最长回文子串长度
2018/01/22 Python
python实现手机通讯录搜索功能
2018/02/22 Python
Python模拟自动存取款机的查询、存取款、修改密码等操作
2018/09/02 Python
详解python做UI界面的方法
2019/02/27 Python
python 在右键菜单中加入复制目标文件的有效存放路径(单斜杠或者双反斜杠)
2020/04/08 Python
Python3基于plotly模块保存图片表格
2020/08/03 Python
Python爬取12306车次信息代码详解
2020/08/12 Python
Python全局变量与global关键字常见错误解决方案
2020/10/05 Python
AmazeUI 加载进度条的实现示例
2020/08/20 HTML / CSS
Pottery Barn阿联酋:购买家具、家居装饰及更多
2019/12/08 全球购物
会计专业职业规划:规划自我赢取未来
2014/02/12 职场文书
请假条范文大全
2014/04/10 职场文书
小学评语大全
2014/04/22 职场文书
禁止高声喧哗的标语
2014/06/11 职场文书
2016年第32个教师节红领巾广播稿
2015/12/18 职场文书
廉政党课工作报告案例
2019/06/21 职场文书