Flask干货 flask钩子函数应用

钩子函数
before_first_request
before_request
after_request
teardown_appcontext
template_filter
context_processor
errorhandler
Flask信号机制
自定义信号
Flask中引用信号
Flask内置信号
内置信号
template_rendered
got_request_exception
钩子函数
钩子函数是在一个事件触发的时候 。在系统级捕获到了他 。然后做一些操作 。一段用以处理系统消息的程序 。“钩子”就是在某个阶段给你一个做某些处理的机会;
before_first_request
处理初次请求Flask项目之前执行;
from flask import Flask
app = Flask(__name__)
@app.before_first_request # 只在Flask项目启动之后初次访问的时候执行;
def first_request():
print('before_first_request')
if __name__ == '__main__':
app.run(debug=True, port=80)
before_request
在每次请求之前执行 。通常可以用这个装饰器来给视图函数增加一些变量;
from flask import Flask
app = Flask(__name__)
@app.before_request # 每次请求视图函数之前都会执行
def before_request():
print('before_request')
if __name__ == '__main__':
app.run(debug=True, port=80)
after_request
在每次请求之前执行 。通常可以用这个装饰器来给视图函数增加一些变量;
from flask import Flask
app = Flask(__name__)
@app.after_request # 每次请求视图函数之后都会执行
def after_request():
print('after_request')
if __name__ == '__main__':
app.run(debug=True, port=80)
teardown_appcontext
不管是否有异常 。注册的函数都会在每次请求之后执行;
from flask import Flask
app = Flask(__name__)
@app.teardown_appcontext
def teardown(exc=None):
if exc is None:
db.session.commit()
else:
db.session.rollback()
db.session.remove()
if __name__ == '__main__':
app.run(debug=True, port=80)
template_filter
在使用Jinja2模板的时候自定义过滤器 。比如可以增加一个upper的过滤器,jinja2文档里有具体使用方法;
@app.template_filter
def upper_filter(s):
return s.upper()
context_processor
上下文处理器 。返回的字典中的键可以在模板上下文中使用;
@app.context_processor
return {'current_user':'xxx'}
errorhandler
errorhandler接收状态码 。可以自定义返回这种状态码的响应的处理方法,只会捕获错误code 。正确的比如2xx/3xx都无法使用该功能;
from flask import Flask, abort
app = Flask(__name__)
@app.route('/')
def home():
abort(400) # 手动抛出400错误
return 'home'
@app.errorhandler(400)
def errorHandler(error): # 需要传入一个参数 。接收错误信息
print(error)
return '400 Page'
if __name__ == '__main__':
app.run(debug=True, port=80)
Flask信号机制
从Flask 0.6 开始 。Flask 中集成支持信号 。这种支持是由优秀的 blinker 库提供 。并且当它不可用时会优雅地退回 。信号是什么?信号通过在核心框架的其它地方或 Flask 扩展的动作发生时的发送通知来帮助你解耦应用,说实话就是一种消息通知的机制;
其实这里的信号就是日常理解的信号 。只是一种信息标号 。它本身没有什么特殊含义 。咱们会事先约定好信号的的含义(定义信号) 。通常咱们说的监听信号 。是服务器监听信号会什么时候发生;这里使用订阅是相对咱们而言的(因为信号最终是要反映给咱们人看的) 。像订阅公众账号一样订阅信号 。当这类信号发生时 。咱们知道发生了什么 。那咱们可以知道下一步该做什么了 。而Flask信号(signals, or event hooking)允许特定的发送端通知订阅者发生了什么 。
自定义信号
from blinker import Namespace
# 定义一个信号
namespace = Namespace() # 生成一个命名空间的对象
login_signal = namespace.signal('login') # 通过namespace来创建一个login的信号通道
# 定义一个当接接到信号之后的处理函数
def login(sender, username):
'''
:param sender: 信号的发送者
:param username: 接收参数
'''
print('%s登录了 。是由%s发送的' % (username, sender.__name__))
# 监听信号
login_signal.connect(login)
# 定义一个发送者
def test():
print('cce')
login_signal.send(test, username='cce') # 传入信号的发送者 。和参数
Flask中引用信号
// app.py
from flask import Flask, abort, request
from signals import login_signal # 导入信号对象
app = Flask(__name__)
@app.route('/login')
def login():
username = request.args.get('username', None)
if username:
login_signal.send(app,username=username) # 当客户登录了之后发送信号
return '登录成功'
return '请输入客户名'
if __name__ == '__main__':
app.run(debug=True, port=80)
// signals.py
from blinker import Namespace
# 定义一个信号
namespace = Namespace() # 生成一个命名空间的对象
login_signal = namespace.signal('login') # 通过namespace来创建一个login的信号通道
# 定义一个当接接到信号之后的处理函数
def login(sender, username):
'''
:param sender: 信号的发送者
:param username: 接收参数
'''
print('%s登录了 。是由%s发送的' % (username, sender)) # cce登录了 。是由<Flask 'app'>发送的
# 监听信号
login_signal.connect(login)
Flask内置信号
Flask内置了9种信号 。并且 。每次触发了相应信号的事件 。都会自动发起信号 。所以咱们只要定义信号 。和监听信号即可;
内置信号
request_started:请求到来前执行;
request_finished:请求结束后执行;
before_render_template:模板渲染前执行;
template_rendered:模板渲染后执行;
got_request_exception:请求执行出现错误异常时执行;
request_tearing_down:请求执行完毕后自动执行(无论成功与否);
【Flask干货 flask钩子函数应用】appcontext_tearing_down:请求上下文执行完毕后自动执行(无论成功与否);
appcontext_pushed:请求上下文push时执行;
appcontext_popped:请求上下文pop时执行;
message_flashed:调用flask在其中添加数据时 。自动触发;
template_rendered
模板渲染后执行;
from flask import Flask, render_template, template_rendered # 导入Flask内置信号
app = Flask(__name__)
def template_rendered_func(sender,*args,**kwargs): # 定义信号处理函数
print(sender)
print(args)
print(kwargs)
template_rendered.connect(template_rendered_func) # 监听信号,查看源码 Flask发送的信号是template_rendered.send(app, template=template, context=context)
@app.route('/login')
def home():
return render_template('home.html')
if __name__ == '__main__':
app.run(debug=True, port=80)
got_request_exception
请求执行出现错误异常时,将异常信息记录在案;
from flask import Flask, render_template, got_request_exception # 导入Flask内置信号
app = Flask(__name__)
def got_request_exception_func(sender,*args,**kwargs): # 定义信号处理函数
print(sender)
print(args)
print(kwargs)
got_request_exception.connect(got_request_exception_func) # 监听信号,此时得到结果{'exception': NameError("name 'request' is not defined",)}
@app.route('/login')
def home():
print(request.cce) # 此处会抛出错误
return render_template('home.html')
if __name__ == '__main__':
app.run(debug=True, port=80)