目录

Django信号介绍

Django内置信号

  • 信号种类
  • 信号注册

自定义信号

实测

  • 内置信号
  • 自定义信号

Django信号介绍

Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。

比如在数据库操作,插入一条数据之前和之后都写入日志。

这里装饰器就实现不了了,装饰器用在函数上,这里可能在一条代码前后,而且是每次。

Django是非常牛逼的框架,在很多地方都放置了钩子。我们调用钩子就可以了。

我们可以在信号里面注册很多个函数。触发信号时,会把信号里的函数执行一遍。

Django内置信号

信号种类

# 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 # 创建数据库连接时,自动触发

信号注册

对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:

from django.core.signals import request_started
from django.core.signals import request_finished
from django.core.signals import got_request_exception from django.db.models.signals import class_prepared
from django.db.models.signals import pre_init, post_init
from django.db.models.signals import pre_save, post_save
from django.db.models.signals import pre_delete, post_delete
from django.db.models.signals import m2m_changed
from django.db.models.signals import pre_migrate, post_migrate from django.test.signals import setting_changed
from django.test.signals import template_rendered from django.db.backends.signals import connection_created ################### 方法一 xxoo.connect(func) ###################
def func1(sender,*args, **kwargs):
print("request_started_func1")
print(sender,args,kwargs) # 两个参数会把内容传递给信号 def func2(sender,*args, **kwargs):
print("request_finished_func2")
print(sender,args,kwargs) # 两个参数会把内容传递给信号 request_started.connect(func1) # 信号注册函数func1。request_started指上述导入的信号
request_finished.connect(func2) # 信号注册函数func2。request_finished指上述导入的信号 ################### 方法二 @receiver(xxoo)###################
from django.core.signals import request_started
from django.core.signals import request_finished
from django.dispatch import receiver @receiver(request_started)
def func3(sender,*args, **kwargs):
print("request_started_func3")
print(sender,args,kwargs) # 两个参数会把内容传递给信号 @receiver(request_finished)
def func4(sender,*args, **kwargs):
print("request_finished_func4")
print(sender,args,kwargs) # 两个参数会把内容传递给信号

如何调用执行

  • views.py里直接写入上述代码
  • __init__.py写入上述代码(推荐):可以在project下的同名目录下__init__.py里导入这个文件,这样一运行就自动注册了

自定义信号

定义信号

import django.dispatch
sg_name = django.dispatch.Signal(providing_args=["toppings", "size"]) # 触发信号至少要传两个参数

注册信号

def callback(sender, **kwargs):
print("callback")
print(sender,kwargs) sg_name.connect(callback)

触发信号

from 路径 import sg_name

sg_name.send(sender='发送者随便填',toppings=123, size=456)

由于内置信号的触发者已经集成到Django中,所以其会自动调用,而对于自定义信号则需要开发者在任意位置触发。

比如对系统状态阀值设置,到达某个状态,触发信号。

这样只注册信号就可以,类似插拔式,降低程序耦合。

实测

内置信号

from django.core.signals import request_started
from django.core.signals import request_finished
from django.core.signals import got_request_exception from django.db.models.signals import class_prepared
from django.db.models.signals import pre_init, post_init
from django.db.models.signals import pre_save, post_save
from django.db.models.signals import pre_delete, post_delete
from django.db.models.signals import m2m_changed
from django.db.models.signals import pre_migrate, post_migrate from django.test.signals import setting_changed
from django.test.signals import template_rendered from django.db.backends.signals import connection_created ################### 方法一 xxoo.connect(func) ###################
def func1(sender,*args, **kwargs):
print("request_started_func1")
print(sender,args,kwargs) # 两个参数会把内容传递给信号 def func2(sender,*args, **kwargs):
print("request_finished_func2")
print(sender,args,kwargs) # 两个参数会把内容传递给信号 request_started.connect(func1) # 信号注册函数func1。request_started指上述导入的信号
request_finished.connect(func2) # 信号注册函数func2。request_finished指上述导入的信号 ################### 方法二 @receiver(xxoo)###################
from django.core.signals import request_started
from django.core.signals import request_finished
from django.dispatch import receiver @receiver(request_started)
def func3(sender,*args, **kwargs):
print("request_started_func3")
print(sender,args,kwargs) # 两个参数会把内容传递给信号 @receiver(request_finished)
def func4(sender,*args, **kwargs):
print("request_finished_func4")
print(sender,args,kwargs) # 两个参数会把内容传递给信号

__init__.py

from django.shortcuts import render,HttpResponse
import time def index(request):
ctime = time.time()
print("index.html")
return render(request,"index1.html",{"ctime":ctime})

views.py

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>{{ ctime }}</h2>
</body>
</html>

index1.html

# 结果
request_started_func1
<class 'django.core.handlers.wsgi.WSGIHandler'> () {'signal': <django.dispatch.dispatcher.Signal object at 0x09CD0950>, 'environ': ...略}}
request_started_func3
<class 'django.core.handlers.wsgi.WSGIHandler'> () {'signal': <django.dispatch.dispatcher.Signal object at 0x09CD0950>, 'environ': ...略}}
index.html
request_finished_func2
<class 'django.core.handlers.wsgi.WSGIHandler'> () {'signal': <django.dispatch.dispatcher.Signal object at 0x09CD0970>}
request_finished_func4
<class 'django.core.handlers.wsgi.WSGIHandler'> () {'signal': <django.dispatch.dispatcher.Signal object at 0x09CD0970>}

自定义信号

import django.dispatch
sg_name = django.dispatch.Signal(providing_args=["toppings", "size"]) # 触发信号至少要传两个参数 def callback(sender, **kwargs):
print("callback")
print(sender,kwargs) sg_name.connect(callback)

__init__.py

from . import sg_name

from django.shortcuts import render,HttpResponse
import time def index(request):
ctime = time.time()
print("index.html")
sg_name.send(sender='发送者随便填', toppings=123, size=456) # 需要手动触发
return render(request,"index1.html",{"ctime":ctime})

views.py

# 结果

index.html
callback
发送者随便填 {'signal': <django.dispatch.dispatcher.Signal object at 0x0A6BFC30>, 'toppings': 123, 'size': 456}

Django_信号的更多相关文章

  1. Boost信号/槽signals2

    信号槽是Qt框架中一个重要的部分,主要用来解耦一组互相协作的类,使用起来非常方便.项目中有同事引入了第三方的信号槽机制,其实Boost本身就有信号/槽,而且Boost的模块相对来说更稳定. signa ...

  2. 为什么房间的 Wi-Fi 信号这么差

    最近把家里主卧整成了个小影院,由于之前房子装修时网线端口与电源插口布置太少,导致家庭网络架设变得麻烦起来,最后终于通过「无线中继」技术达到了全屋满格 Wi-Fi 的效果. 在 Wi-Fi 架设过程中, ...

  3. qt5中信号和槽的新语法

    qt5中的连接 有下列几种方式可以连接到信号上 旧语法 qt5将继续支持旧的语法去连接,在QObject对象上定义信号和槽函数,及任何继承QObjec的对象(包含QWidget). connect(s ...

  4. C# - 多线程 之 信号系统

    基础概览 多线程之信号系统命名空间 using System.Threading; 线程同步类的继承层次关系图 终止状态和非终止状态 在终止状态下,被WaitOne()阻塞的线程会逐个得到释放.如果一 ...

  5. Qt信号与槽自动关联机制

    参考链接1:http://blog.csdn.net/skyhawk452/article/details/6121407 参考链接2:http://blog.csdn.net/memory_exce ...

  6. Linux 信号(二)—— signal 函数

    弗洛伊德认为:要解决这些苦恼,当事人就要通过回忆并理解自己早期的童年经历,来获得对潜意识冲突的顿悟.弗洛伊德的疗法被称为“精神分析” (psychoanalysis),在 20 世纪的很长一段时间被心 ...

  7. Linux 信号(一)—— kill 函数

    世事并无好坏之分,全看我们怎么去想.—— 哈姆雷特·第二幕第二景 ilocker:关注 Android 安全(新入行,0基础) QQ: 2597294287 #include <signal.h ...

  8. django 缓存、中间件、信号、CSRF 详解

    中间件 django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法. 在django项 ...

  9. PHP进程通信基础——信号

    PHP进程通信基础--信号 使用信号通信.可以使用kill -l 来查看当前系统的信号类型. 每个信号所代表的的详细含义,请查看我的这篇博客:http://www.cnblogs.com/roverl ...

随机推荐

  1. Spring源码分析(二十三)BeanFactory的后处理

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.激活注册的 BeanFactoryPostProcessor ...

  2. 【ThinkingInC++】75、多重继承

    第九章 多重继承 9.2 接口继承 Intertfacees.cpp /** * 书本:[ThinkingInC++] * 功能:接口继承Interfaces.cpp * 时间:2014年10月28日 ...

  3. 【CSS3】特殊的属性归纳(一)

    CSS3手册地址速查表 -webkit- 最终要用兼容性写法 (一)-webkit-tap-highlight-color    (mobile移动设备私有属性) 案列: 问题:遇到a链接和butto ...

  4. Tomcat出现需要输入账号和密码问题

    这里是端口冲突问题: 可以做一下几个解决方案: 第一:更好Tomcat/conf/server.xml文件里面的制定8080端口号,更改为你能记住的端口数: 第二:找到冲突的端口的进程,杀死这个进程, ...

  5. python学习之路(1)

    今天刚入门python,对于有c和java基础的我,学习起来还是比较容易的,我并没有用PyCharm写,而是最基础的IDLE,学习python比java容易的地方就是不要写分号,不要打包,不要定义等等 ...

  6. 20155212 C语言实现linux下pwd命令的两种方法

    20155212 C语言实现linux下pwd命令的两种方法 学习pwd命令 通过man pwd命令查看 pwd [OPTION],一般不加参数 -P显示当前目录的物理路径 -L显示当前目录的连接路径 ...

  7. 20145209刘一阳《JAVA程序设计》第三周课堂测试

    第三周课堂测试 1.使用汇编语言编写指令时,用一些简单的容易记忆的符号来代替二进制指令,比机器语言更为方便,属于高级语言.(B) A .true B .false 2.下列说法正确的是(ABCD) A ...

  8. Caffe on Windows (Visual Studio 2015+CUDA8.0+cuDNNv5)

    Title : Caffe (Visual Studio15+CUDA8+cuDNN5+python3.5) Author : SURFZJY Logo : True [TITLE] Requirem ...

  9. [APIO2018] Duathlon 铁人两项 圆方树,DP

    [APIO2018] Duathlon 铁人两项 LG传送门 圆方树+简单DP. 不会圆方树的话可以看看我的另一篇文章. 考虑暴力怎么写,枚举两个点,答案加上两个点之间的点的个数. 看到题面中的一句话 ...

  10. Codeforces 374 C. Travelling Salesman and Special Numbers (dfs、记忆化搜索)

    题目链接:Travelling Salesman and Special Numbers 题意: 给了一个n×m的图,图里面有'N','I','M','A'四种字符.问图中能构成NIMA这种序列最大个 ...