目录

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. salt常用命令(一)

    查看模块包含哪些函数 salt 'node' sys.list_functions test 查看函数的用法 salt 'node' sys.doc test.echo 使用模块中的函数 salt ' ...

  2. 初识Qt简单动画

    Qt提供了类QPropertyAnimation来实现图片的一些简单的动画操作效果. 1.新建一个Qt空项目,同时添加资源文件,并在资源文件中添加图片路径.之后在main.cpp函数中添加以下代码 # ...

  3. 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 ...

  4. Jmeter新手频犯错误之一(登录)

    昨天被人问了一个问题:为什么我用Jmeter先创建一个登录请求,然后创建一个操作(比如计算账单)请求,运行之后结果树中却是status_code=401(即登录失败),我明明登录了啊.... emmm ...

  5. Mac OS X 命令行用户应当知道的八个终端工具

    原文链接:Eight Terminal Utilities Every OS X Command Line User Should Know OS X  的Terminal 终端开辟了强大的UNIX实 ...

  6. 非const引用参数传入不同类型编译不过的理解(拒绝将临时对象绑定为非const的引用的形参是有道理的)

    int f (int & I) { cout<<I<<std::endl; } void main() { long L; f(L); // 编译不过 f((int)L ...

  7. package.json常用的字段

    package.json中5个字段: name: 包名 今后下载时输入名称 (注意:要与下载的包名不一样) version:版本号 x.x.x 例如 1.2.3 1 大版本:当这个包有巨大内容变化时( ...

  8. 更新Android Studio 3.1.1碰到的问题

    碰到了如下问题 The SourceSet 'instrumentTest' is not recognized by the Android Gradle Plugin. Perhaps you m ...

  9. hadoop在CentOS下的安装配置

    版本:CentOS-6.8-x86_64-minimal,hadoop2.6.4,jdk1.7.0 首先把jdk.hadoop压缩包下载发送到CentOS下并解压 下载发送不多赘述,解压命令tar - ...

  10. python3安装crypto出错,及解决方法

    首先我用的python3.5的版本 问题的由来,我想通过python去实现RSA加密算法时,破解某网站的js加密认证,网上说需要安装pycrypto,我就去进行pip安装了 pip install p ...