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_信号的更多相关文章
- Boost信号/槽signals2
信号槽是Qt框架中一个重要的部分,主要用来解耦一组互相协作的类,使用起来非常方便.项目中有同事引入了第三方的信号槽机制,其实Boost本身就有信号/槽,而且Boost的模块相对来说更稳定. signa ...
- 为什么房间的 Wi-Fi 信号这么差
最近把家里主卧整成了个小影院,由于之前房子装修时网线端口与电源插口布置太少,导致家庭网络架设变得麻烦起来,最后终于通过「无线中继」技术达到了全屋满格 Wi-Fi 的效果. 在 Wi-Fi 架设过程中, ...
- qt5中信号和槽的新语法
qt5中的连接 有下列几种方式可以连接到信号上 旧语法 qt5将继续支持旧的语法去连接,在QObject对象上定义信号和槽函数,及任何继承QObjec的对象(包含QWidget). connect(s ...
- C# - 多线程 之 信号系统
基础概览 多线程之信号系统命名空间 using System.Threading; 线程同步类的继承层次关系图 终止状态和非终止状态 在终止状态下,被WaitOne()阻塞的线程会逐个得到释放.如果一 ...
- Qt信号与槽自动关联机制
参考链接1:http://blog.csdn.net/skyhawk452/article/details/6121407 参考链接2:http://blog.csdn.net/memory_exce ...
- Linux 信号(二)—— signal 函数
弗洛伊德认为:要解决这些苦恼,当事人就要通过回忆并理解自己早期的童年经历,来获得对潜意识冲突的顿悟.弗洛伊德的疗法被称为“精神分析” (psychoanalysis),在 20 世纪的很长一段时间被心 ...
- Linux 信号(一)—— kill 函数
世事并无好坏之分,全看我们怎么去想.—— 哈姆雷特·第二幕第二景 ilocker:关注 Android 安全(新入行,0基础) QQ: 2597294287 #include <signal.h ...
- django 缓存、中间件、信号、CSRF 详解
中间件 django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法. 在django项 ...
- PHP进程通信基础——信号
PHP进程通信基础--信号 使用信号通信.可以使用kill -l 来查看当前系统的信号类型. 每个信号所代表的的详细含义,请查看我的这篇博客:http://www.cnblogs.com/roverl ...
随机推荐
- salt常用命令(一)
查看模块包含哪些函数 salt 'node' sys.list_functions test 查看函数的用法 salt 'node' sys.doc test.echo 使用模块中的函数 salt ' ...
- 初识Qt简单动画
Qt提供了类QPropertyAnimation来实现图片的一些简单的动画操作效果. 1.新建一个Qt空项目,同时添加资源文件,并在资源文件中添加图片路径.之后在main.cpp函数中添加以下代码 # ...
- Caused by: org.apache.velocity.exception.MethodInvocationException: Invocation of method 'getUser' in class org.uncommons.reportng.ReportMetadata threw exception class java.net.UnknownHostException :
Running TestSuite [TestNG] [WARN] Ignoring duplicate listener : org.uncommons.reportng.HTMLReporter ...
- Jmeter新手频犯错误之一(登录)
昨天被人问了一个问题:为什么我用Jmeter先创建一个登录请求,然后创建一个操作(比如计算账单)请求,运行之后结果树中却是status_code=401(即登录失败),我明明登录了啊.... emmm ...
- Mac OS X 命令行用户应当知道的八个终端工具
原文链接:Eight Terminal Utilities Every OS X Command Line User Should Know OS X 的Terminal 终端开辟了强大的UNIX实 ...
- 非const引用参数传入不同类型编译不过的理解(拒绝将临时对象绑定为非const的引用的形参是有道理的)
int f (int & I) { cout<<I<<std::endl; } void main() { long L; f(L); // 编译不过 f((int)L ...
- package.json常用的字段
package.json中5个字段: name: 包名 今后下载时输入名称 (注意:要与下载的包名不一样) version:版本号 x.x.x 例如 1.2.3 1 大版本:当这个包有巨大内容变化时( ...
- 更新Android Studio 3.1.1碰到的问题
碰到了如下问题 The SourceSet 'instrumentTest' is not recognized by the Android Gradle Plugin. Perhaps you m ...
- hadoop在CentOS下的安装配置
版本:CentOS-6.8-x86_64-minimal,hadoop2.6.4,jdk1.7.0 首先把jdk.hadoop压缩包下载发送到CentOS下并解压 下载发送不多赘述,解压命令tar - ...
- python3安装crypto出错,及解决方法
首先我用的python3.5的版本 问题的由来,我想通过python去实现RSA加密算法时,破解某网站的js加密认证,网上说需要安装pycrypto,我就去进行pip安装了 pip install p ...