深入理解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 fabric实现远程操作和部署示例
Mar 25 Python
Tornado服务器中绑定域名、虚拟主机的方法
Aug 22 Python
Django中使用group_by的方法
May 26 Python
Python三种遍历文件目录的方法实例代码
Jan 19 Python
Python针对给定列表中元素进行翻转操作的方法分析
Apr 27 Python
python format 格式化输出方法
Jul 16 Python
Python3爬虫学习之将爬取的信息保存到本地的方法详解
Dec 12 Python
对python模块中多个类的用法详解
Jan 10 Python
python处理自动化任务之同时批量修改word里面的内容的方法
Aug 23 Python
使用Python给头像戴上圣诞帽的图像操作过程解析
Sep 20 Python
python smtplib发送多个email联系人的实现
Oct 09 Python
python爬取代理ip的示例
Dec 18 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
收音机怀古---春雷3P7图片欣赏
2021/03/02 无线电
用PHP函数解决SQL injection
2006/12/09 PHP
php定时删除文件夹下文件(清理缓存文件)
2013/01/23 PHP
PHP封装的PDO数据库操作类实例
2017/06/21 PHP
PHP htmlspecialchars()函数用法与实例讲解
2019/03/08 PHP
PHP中16个高危函数整理
2019/09/19 PHP
js 数组操作代码集锦
2009/04/28 Javascript
用js实现table单元格高宽调整,兼容合并单元格(兼容IE6、7、8、FF)实例
2013/06/25 Javascript
解决用jquery load加载页面到div时,不执行页面js的问题
2014/02/22 Javascript
JavaScript获取表单内所有元素值的方法
2015/04/02 Javascript
PHP+jQuery+Ajax+Mysql如何实现发表心情功能
2015/08/06 Javascript
前端页面文件拖拽上传模块js代码示例
2017/05/19 Javascript
EasyUI框架 使用Ajax提交注册信息的实现代码
2017/09/27 Javascript
JS实现网页抢购功能(触发,终止脚本)
2017/11/27 Javascript
解决vue同一slot在组件中渲染多次的问题
2018/09/06 Javascript
vue项目开启Gzip压缩和性能优化操作
2020/10/26 Javascript
springboot+vue实现文件上传下载
2020/11/17 Vue.js
[00:35]DOTA2上海特级锦标赛 EG战队宣传片
2016/03/04 DOTA
Python只用40行代码编写的计算器实例
2017/05/10 Python
Python错误处理操作示例
2018/07/18 Python
对numpy中的where方法嵌套使用详解
2018/10/31 Python
Python 使用 attrs 和 cattrs 实现面向对象编程的实践
2019/06/12 Python
python求最大值,不使用内置函数的实现方法
2019/07/09 Python
python3字符串操作总结
2019/07/24 Python
解决torch.autograd.backward中的参数问题
2020/01/07 Python
pycharm 2019 最新激活方式(pycharm破解、激活)
2020/09/22 Python
CSS3实现酷炫的3D旋转透视效果
2019/11/21 HTML / CSS
html5 利用canvas实现超级玛丽简单动画
2013/09/06 HTML / CSS
Sunglass Hut巴西网上商店:男女太阳镜
2020/10/04 全球购物
大一军训感言
2014/01/09 职场文书
幼儿园教师工作感言
2014/02/15 职场文书
建筑工程质量通病防治方案
2014/06/08 职场文书
群众路线班子对照检查材料
2014/09/25 职场文书
2015选调生工作总结
2015/07/24 职场文书
网络新闻该怎么写?这些写作技巧你都知道吗?
2019/08/26 职场文书
十大公认最好看的动漫:《咒术回战》在榜,《钢之炼金术师》第一
2022/03/18 日漫