flask 源码专题(九):flask扩展点
1. 信号(源码)
信号,是在flask框架中为我们预留的钩子,让我们可以进行一些自定义操作。
pip3 install blinker
2. 根据flask项目的请求流程来进行设置扩展点
中间件
# 代码示例 from flask import Flask,render_template app = Flask(__name__) @app.route('/index')
def index():
return render_template('index.html') @app.route('/order')
def order():
return render_template('order.html') class MyMiddleware(object):
def __init__(self,old_app):
self.wsgi_app = old_app.wsgi_app def __call__(self, *args, **kwargs):
print('123')
result = self.wsgi_app(*args, **kwargs)
print('456')
return result app.wsgi_app = MyMiddleware(app) if __name__ == '__main__':
app.run()
当app_ctx被push到local中栈之后,会触发appcontext_pushed信号,之前注册在这个信号中的方法,就会被执行。
# 代码示例 from flask import Flask,render_template
from flask import signals app = Flask(__name__) @signals.appcontext_pushed.connect
def f1(arg):
print('appcontext_pushed信号f1被触发',arg) @signals.appcontext_pushed.connect
def f2(arg):
print('appcontext_pushed信号f2被触发',arg) @app.route('/index')
def index():
return render_template('index.html') @app.route('/order')
def order():
return render_template('order.html') if __name__ == '__main__':
app.run()
# app.__call__执行before_first_request扩展
# 代码示例 from flask import Flask,render_template app = Flask(__name__) @app.before_first_request
def f2():
print('before_first_requestf2被触发') @app.route('/index')
def index():
return render_template('index.html') @app.route('/order')
def order():
return render_template('order.html') if __name__ == '__main__':
app.run()
request_started信号
# 代码示例 from flask import Flask,render_template
from flask import signals
app = Flask(__name__) @signals.request_started.connect
def f3(arg):
print('request_started信号被触发',arg) @app.route('/index')
def index():
return render_template('index.html') @app.route('/order')
def order():
return render_template('order.html') if __name__ == '__main__':
app.run()
url_value_processor
# 代码示例 from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__) @app.url_value_preprocessor
def f5(endpoint,args):
print('f5') @app.route('/index/')
def index():
print('index')
return render_template('index.html') @app.route('/order')
def order():
print('order')
return render_template('order.html') if __name__ == '__main__':
app.run()
before_reuqest
# 代码示例 from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__) @app.before_request
def f6():
g.xx = 123
print('f6') @app.route('/index/')
def index():
print('index')
return render_template('index.html') @app.route('/order')
def order():
print('order')
return render_template('order.html') if __name__ == '__main__':
app.run()
视图函数
before_render_template / rendered_template
# 代码示例 from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__) @signals.before_render_template.connect
def f7(app, template, context):
print('f7') @signals.template_rendered.connect
def f8(app, template, context):
print('f8') @app.route('/index/')
def index():
return render_template('index.html') @app.route('/order')
def order():
print('order')
return render_template('order.html') if __name__ == '__main__':
app.run()after_request
# 代码示例 from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__) @app.after_request
def f9(response):
print('f9')
return response @app.route('/index/')
def index():
return render_template('index.html') @app.route('/order')
def order():
print('order')
return render_template('order.html') if __name__ == '__main__':
app.run()
request_finished
# 代码示例 from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__) @signals.request_finished.connect
def f10(app,response):
print('f10') @app.route('/index/')
def index():
return render_template('index.html') @app.route('/order')
def order():
print('order')
return render_template('order.html') if __name__ == '__main__':
app.run()
got_request_exception
# 代码示例 from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__) @app.before_first_request
def test():
int('asdf') @signals.got_request_exception.connect
def f11(app,exception):
print('f11') @app.route('/index/')
def index():
return render_template('index.html') @app.route('/order')
def order():
print('order')
return render_template('order.html') if __name__ == '__main__':
app.run()
teardown_request
# 代码示例 from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__) @app.teardown_request
def f12(exc):
print('f12') @app.route('/index/')
def index():
return render_template('index.html') @app.route('/order')
def order():
print('order')
return render_template('order.html') if __name__ == '__main__':
app.run()
request_tearing_down
# 代码示例 from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__) @signals.request_tearing_down.connect
def f13(app,exc):
print('f13') @app.route('/index/')
def index():
return render_template('index.html') @app.route('/order')
def order():
print('order')
return render_template('order.html') if __name__ == '__main__':
app.run()
appcontext_popped
# 代码示例 from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__) @signals.appcontext_popped.connect
def f14(app):
print('f14') @app.route('/index/')
def index():
return render_template('index.html') @app.route('/order')
def order():
print('order')
return render_template('order.html') if __name__ == '__main__':
app.run()扩展:flash
flash存值之后只能取一次
# 代码示例 from flask import Flask,render_template,flash,get_flashed_messages,session
from flask import signals
app = Flask(__name__)
app.secret_key = 'iuknsoiuwknlskjdf' @app.route('/index/')
def index():
# flash('123')
session['k1'] = 123
return render_template('index.html') @app.route('/order')
def order():
# messages = get_flashed_messages()
# print(messages)
val = session['k1']
del session['k1']
print(val)
return render_template('order.html') if __name__ == '__main__':
app.run()
总结:
- 关于flask内部共有14+个扩展点用于我们对flask框架内部进行定制,其中有:9个是信号。
# 源码示例
template_rendered = _signals.signal("template-rendered")
before_render_template = _signals.signal("before-render-template")
request_started = _signals.signal("request-started")
request_finished = _signals.signal("request-finished")
request_tearing_down = _signals.signal("request-tearing-down")
got_request_exception = _signals.signal("got-request-exception")
appcontext_tearing_down = _signals.signal("appcontext-tearing-down")
appcontext_pushed = _signals.signal("appcontext-pushed")
appcontext_popped = _signals.signal("appcontext-popped")
message_flashed = _signals.signal("message-flashed")
执行顺序
2. request_started = _signals.signal('request-started') # 请求到来前执行
5. request_finished = _signals.signal('request-finished') # 请求结束后执行
3. before_render_template = _signals.signal('before-render-template') # 模板渲染前执行
4. template_rendered = _signals.signal('template-rendered') # 模板渲染后执行
发生在2/3/4/5或不执行 got_request_exception = _signals.signal('got-request-exception') # 请求执行出现异常时执行
6. request_tearing_down = _signals.signal('request-tearing-down') # 请求执行完毕后自动执行(无论成功与否)
7. appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 请求上下文执行完毕后自动执行(无论成功与否)
1. appcontext_pushed = _signals.signal('appcontext-pushed') # 请求app上下文push时执行
8. appcontext_popped = _signals.signal('appcontext-popped') # 请求上下文pop时执行
message_flashed = _signals.signal('message-flashed') # 调用flask在其中添加数据时,自动触发
自定义信号
第一步:创建信号
第二步:将函数注册到信号中: 添加到这个列表
第三步: 发送信号
第四步:运行
具体实现:可参考flask源码,写一个自定义信号
from flask import Flask,flash
from flask.signals import _signals
app = Flask(__name__) xinhao = _signals.signal("xinhao")#创建信号
#定义函数
def wahaha(*args,**kwargs):
print("",args,kwargs) def sww(*args,**kwargs):
print("",args,kwargs)
# 将函数注册到信号中,添加到这个列表
xinhao.connect(wahaha)
xinhao.connect(sww) @app.route("/zzz")
def zzz():
xinhao.send(sender='xxx',a1=123,a2=456) #触发这个信号,执行注册到这个信号列表中的所有函数,此处的参数个数需要与定义的函数中的参数一致
return "发送信号成功" if __name__ == '__main__':
app.run(debug=True) #打印结果
# 111 (None,) {'sender': 'xxx', 'a1': 123, 'a2': 456}
# 222 (None,) {'sender': 'xxx', 'a1': 123, 'a2': 456}
flask 源码专题(九):flask扩展点的更多相关文章
- Flask源码解读--所有可扩展点
一.前言 flask中有很多可扩展点(笔者这样称呼),其中包含了信号和请求钩子,这些信号和钩子有什么用呢?其主要作用用于帮助我们进行程序的耦合性,当然还可以让我们自定义一些行为.话不多说,通过阅读源码 ...
- flask 源码专题(五):SqlAlchemy 中操作数据库时session和scoped_session的区别
1原生session: from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine from sqlalc ...
- flask 源码专题(二):请求上下文与全文上下文
源码解析 0. 请求入口 if __name__ == '__main__': app.run() def run(self, host=None, port=None, debug=None, lo ...
- 08 Flask源码剖析之flask拓展点
08 Flask源码剖析之flask拓展点 1. 信号(源码) 信号,是在flask框架中为我们预留的钩子,让我们可以进行一些自定义操作. pip3 install blinker 2. 根据flas ...
- flask 源码专题(十一):LocalStack和Local对象实现栈的管理
目录 04 LocalStack和Local对象实现栈的管理 1.源码入口 1. flask源码关于local的实现 2. flask源码关于localstack的实现 3. 总结 04 LocalS ...
- flask 源码专题(八):路由加载
1.示例代码 from flask import Flask app = Flask(__name__,static_url_path='/xx') @app.route('/index') def ...
- flask 源码专题(六):session处理机制
前言 flask_session是flask框架实现session功能的一个插件,用来替代flask自带的session实现机制,flask默认的session信息保存在cookie中,不够安全和灵活 ...
- flask 源码专题(一):app.run()的背后
当我们用Flask写好一个app后, 运行app.run()表示监听指定的端口, 对收到的request运行app生成response并返回. 现在分析一下, 运行app.run()后具体发生了什么事 ...
- flask 源码专题(十):flash源码研究
flash源码 def flash(message, category="message"): flashes = session.get("_flashes" ...
随机推荐
- [noi.ac省选模拟赛20200606]赌怪
题目 点这里看题目. 分析 先特判掉\(K=2\)的情况. 首先可以考虑到一个简单 DP : \(f(i)\):前\(i\)张牌的最大贡献. 转移可以\(O(n^2)\)地枚举区间 ...
- 修改MSSQL的端口地址_TcpPort_数据库安装工具_连载_2
修改MSSQL的端口地址_TcpPort,可在程序中调用,从而修改TcpPort Use master Go ------------------------------ --1)在注册表中查询 Pi ...
- 一行代码让你的python运行速度提高100倍
转自:https://www.cnblogs.com/xihuineng/p/10630116.html 加上之后运行速度快了十倍,我的天呐. python一直被病垢运行速度太慢,但是实际上pytho ...
- vue-admin-template搭建后台管理系统的学习(一)
首先我们来看看这个基础模版的目录结构 ├── build // 构建相关 ├── config // 配置相关├── src // 源代码│ ├── api // 所有请求│ ├── ass ...
- C#数据结构与算法系列(十):中缀表达式转后缀表达式
1.具体步骤 1)初始化两个栈:运算符栈s1和储存中间结果的栈s2:2)从左至右扫描中缀表达式:3)遇到操作数时,将其压s2:4)遇到运算符时,比较其与s1栈顶运算符的优先级: (1)如果s1 ...
- 如何用 React 构建前端架构
早期的前端是由后端开发的,最开始的时候仅仅做展示,点一下链接跳转到另外一个页面去,渲染表单,再用Ajax的方式请求网络和后端交互,数据返回来还需要把数据渲染到DOM上.写这样的代码的确是很简单.在We ...
- IDEA中Maven依赖报红处理
一般依赖报红有以下几种原因: 1.setting.xml没有配置好(要配置自行百度) 2.IDEA配置的Local respository和User settings file路径没写对(不要说不会写 ...
- 入门大数据---基于Zookeeper搭建Kafka高可用集群
一.Zookeeper集群搭建 为保证集群高可用,Zookeeper 集群的节点数最好是奇数,最少有三个节点,所以这里搭建一个三个节点的集群. 1.1 下载 & 解压 下载对应版本 Zooke ...
- RS232/485通信方式 保存和加载时数据的处理
RS232/485通信方式 数据以RS232/485方式通信时,以0xA5作为开始码,以0xAE作为结束码.在开始码和结束码之间的0xA5, 0xAA, 0xAE数据需要进行转码. PC端发送数据时将 ...
- Vue 封装axios(四种请求)及相关介绍(十三)
Vue 封装axios(四种请求)及相关介绍 首先axios是基于promise的http库 promise是什么? 1.主要用于异步计算 2.可以将异步操作队列化,按照期望的顺序执行,返回符合预期的 ...