Flask钩子函数
Posted Flask学习笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask钩子函数相关的知识,希望对你有一定的参考价值。
钩子函数
1.什么是钩子函数
在正常执行的代码前后,插入一段想要执行的代码,这称为钩子函数.
2.Flask
中的钩子函数
上一篇分析了源码
flask/app.py
中的Flask()
类,其实它除了实现了应用上下文,请求上下文之外,还实现了一些常用的钩子hook
函数.常见的钩子函数有:
钩子函数 描述 before_first_request
在处理第一个请求前执行,比如连接数据库操作 before_request
在每次执行请求前执行,比如权限校验 after_request
在每次请求之后调用,前提是没有异常抛出 errorhandler
在访问应用出错时,根据错误码,做一些定制 context_processor
上下文钩子,返回一个字典对象,可以在 jinja
模板中使用teardown_request
在响应销毁时,执行一个函数 teardown_appcontext
不管时候有异常,当应用上下文被移除时,执行的函数.
1.before_first_request
只有在处理第一次请求之前会执行,之后都不会执行.
应用场景:可以加载一些函数,用来对网站进行一些测试,检查,如果发现异常,则截断后续的请求,将整个
Flask
应用停止运行.from flask import Flask
app = Flask(__name__)
app.config.update({
'DEBUG':True,
'AUTO_TEMPLATES_RELOAD':True
})
@app.route('/')
def index():
return 'Hello World!'
@app.before_first_request
def test_app():
print('测试服务器运行')
if __name__ == '__main__':
app.run()输出:
127.0.0.1 - - "GET / HTTP/1.1" 200 -
测试服务器运行
127.0.0.1 - - "GET / HTTP/1.1" 200 -
2.before_request
在每个请求之前都会运行的钩子.
应用场景:共享
session
的鉴权函数,请求黑白名单过滤,根据endpoint
进行请求等.from flask import Blueprint,request
bp = Blueprint('api',__name__,url_prefix='/api/')
required = {
'api_register':['email','username','password']
}
@bp.before_request
def before():
if not request.is_json:
print(request.endpoint)
print(request.json)
return '请使用json风格的参数访问'
try:
if request.endpoint in required:
if request.method == 'POST':
missparam_list = [x for x in required[request.endpoint] if x not in request.json.keys()]
if len(missparam_list) > 0:
return '缺少参数'
except Exception as e:
print(e)
return "{}???".format(e)
@bp.route('/test/')
def test():
if request.method == 'POST':
return 'test'
@bp.route('/api_register/')
def register():
return 'hello'比如在验证
session
,来查看用户是否已经登录from flask import Flask,session,g
from model.api import bp
from os import urandom
app = Flask(__name__)
app.config.update({
'DEBUG':True,
'AUTO_TEMPLATES_RELOAD':True,
'SECRET_KEY':urandom(24)
})
@app.route('/')
def index():
session['name']='Python'
return 'Hello World!'
@app.before_first_request
def test_app():
print('测试服务器运行')
app.register_blueprint(bp)
@app.before_request
def before():
name = session.get('name')
if name:
g.name = name
@app.route('/first/')
def first():
if g.name:
return '已登录'
else:
return '请登录'
if __name__ == '__main__':
app.run()
3.after_request
请求完成时执行,但是必须传入一个参数来接受响应对象,并在最后的
return
这个参数,也就是响应内容.场景:一般用于格式化响应结果,包括响应请求头,响应的格式等.
from flask import Flask,session,g
from model.api import bp
from os import urandom
app = Flask(__name__)
app.config.update({
'DEBUG':True,
'AUTO_TEMPLATES_RELOAD':True,
'SECRET_KEY':urandom(24)
})
@app.route('/')
def index():
session['name']='Python'
return 'Hello World!'
@app.before_first_request
def test_app():
print('测试服务器运行')
app.register_blueprint(bp)
@app.before_request
def before():
name = session.get('name')
if name:
g.name = name
@app.route('/first/')
def first():
if g.name:
return '已登录'
else:
return '请登录'
@app.after_request
def after(response):
response.headers['test']='test'
return response
if __name__ == '__main__':
app.run()访问
127.0.0.1/first/
,查看响应头.
4.errorhandler
当访问出错时,根据错误响应码,进行一些定制化的操作,比如返回
404
页面.场景: 定制化错误信息,
404
,500
等.@app.errorhandler
def page_not_fond(error):
return render_template('404.html'),404访问不存在的页面时,它会返回定义的
404.html
❯ curl http://127.0.0.1:5000/sdf
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>也可以在函数中手动抛出错误,这需要使用到
abort()
函数from flask import abort
@app.route('/app/')
def my_app()
# 手动弹出一个错误
abort(404)
return 'test'访问同样会访问到
404.html
❯ curl http://127.0.0.1:5000/app/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
5.context_processor
将一些数据按照字典的格式返回,可以在
jinja
模板中使用.这样就不用在每个视图函数中都去返回一次render_template('xxx.html',info=xxx)
需要注意的是,这个函数必须返回一个字典对象,不管最后的判断函数是怎么样的.
场景:适用多个页面返回一个同样的值.比如登录后,在每个页面的标头都会显示用户的用户名.
# app.py
@app.context_processor
def context():
# 表示登录
if g.name:
return {'username':'Jack'}
else:
return {}
@app.route('/test1/')
def test1():
return render_template('test1.html')
@app.route('/test2/')
def test2():
return render_template('test2.html')在
test1.html\test2.html
中接受username
{# test1.html, test2.html# }
{{ username}}
6.teardown_request
在响应销毁时,执行一个绑定的函数.
after_requtst
:每一个请求之后绑定一个函数,如果请求没有异常teardown_request
:每一个请求之后绑定一个函数,即是有异常场景:销毁数据库
db
连接@app.teardown_request
def teardown():
db = getattr(g,'database',None)
if db is not None:
db.close()
7.teardown_appcontext
- END -不管是否有异常,当
app
的上下文被移除之后执行的函数,可以进行数据库的提交或者回滚.@app.teardown_appcontext
def teardown(cmd=None):
if cmd is None:
db.session.commit()
else:
db.session.rollback()
db.session.remove()
以上是关于Flask钩子函数的主要内容,如果未能解决你的问题,请参考以下文章