Flask:钩子装饰器

Flask提供了一些装饰器让我们很容易在请求到来时和请求执行完后做一些处理,装饰器修饰的函数会被Flask注册,当条件满足时它们会被触发,有点类似于AOP中的通知。

  • @app.before_first_request: 当服务器第一个请求到来时调用
  • @app.before_request: 会在每个请求前执行
  • @app.after_request: 会在每个请求后执行,处理函数必须传入参数接收响应对象并返回(允许修改返回对象),抛出异常时不会调用该函数,该函数必须返回响应对象否则页面无响应。
  • @app.teardown_request: 会在每个请求后执行,请求发生异常时也会被调用,处理函数必须传入参数接收异常信息。

注: @app.after_request和@app.teardown_request修饰的函数必须要有一个参数,分别用于接收响应对象和错误信息。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from flask import Flask

app = Flask(__name__)

@app.before_first_request
def before_first_request():
print("我只在第一个请求到来时触发")

@app.before_request
def before_request():
print("到来了一个请求")

@app.after_request
def after_request(resp):
print("响应之前调用")
return resp

@app.teardown_request
def teardown_request(error):
print("请求之后调用")

@app.route("/")
def index():
print("处理请求中...")
return "Hello World"

if __name__ == "__main__":
app.run()

注: @app.teardown_request修饰的函数在非调试模式下才能在出现异常时被执行

Flask还提供了一个 @app.errorhandler 装饰器用于错误处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from flask import Flask

app = Flask(__name__)

@app.errorhandler(404)
def notFound(error):
return "404"

@app.errorhandler(500)
def notFound(error):
return "500"

@app.route("/")
def index():
return "Hello World"

@app.route("/error")
def error():
result = 1 / 0
return "error"

if __name__ == "__main__":
app.run()

注: 传入装饰器的值为一错误状态码,修饰的函数必须要有一个参数用于接收错误,为了测试500的效果必须关闭调试模式!

经过上面的测试你可能想到这些装饰器的应用场景了,比如说@app.after_request这个装饰器修饰的函数接收一个响应对象,我们拿到了这个响应对象后可以对内容进行修改(虽然很少见)还可以在上面追加COOKIE进行返回。@app.before_request和@app.teardown_request的组合可以用于打开一个资源和关闭一个资源,常见的资源有打开一个数据库连接,这样又有一个问题怎么在一个请求线程中保存信息而多个请求之间互不干扰,也许你会想到通过threading.local(),Flask提供了一个请求上下文对象 g 与request一样它也是一个本地代理对象保存的数据只在当前线程中可见。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from flask import Flask, g
import pymysql

app = Flask(__name__)

@app.before_request
def before_request():
g.conn = pymysql.connect(host="127.0.0.1", port=3306, database="python",
user="root", password="123456", charset="utf8")

@app.teardown_request
def teardown_request(error):
g.conn.close()

@app.route("/user/<int:uid>")
def index(uid):
cur = g.conn.cursor()
cur.execute("SELECT id, name FROM user WHERE id = %s", (uid,))
row = cur.fetchone()
return row[1]

if __name__ == "__main__":
app.run(debug=True)

  • 本文作者: Harmel
  • 本文链接: http://www.harmel.cn/2018/08/flask-hook.html
  • 版权声明: 文章如无特别说明,则表明该文章为原创文章,如需要转载,请注明出处。
  • 本站说明: 本站使用阿里云服务器,如果您喜欢我的网站,欢迎收藏,能捐赠支持一下就再好不过了。