一、程序上下文
Flask接收到来自客户端的请求后,路由到指定的接口进行响应处理并返回处理结果。响应接口需要知道客户端的请求体,即request对象才能进行正确的处理。如果给每个接口函数都传递一个request对象参数,太过冗余,且代码会很难看,因此Flask使用上下文临时将某些对象编程线程内的全局变量,即在同一个线程内,上下文信息可全局共享,且不会干扰到其他的线程环境。
Flask有两种上下文,分别为程序上下文和请求上下文,各自对应的全局变量如下表:
变量名 | 上下文 | 备注 |
current_app | 程序上下文 | 表示当前运行的程序实例 |
g | 程序上下文 | 处理请求时用作临时存储对象,每次请求都会重新设值 |
request | 请求上下文 | 客户端发来的request请求对象 |
session | 请求上下文 | 请求携带的会话信息 |
Flask在分发请求之前会激活上下文信息,在请求处理完成后再删除。上下文只有在激活后,才可使用对应的全局变量,否则会报异常。
app_ctx = app.app_context() #可获取app对应的上下文
app_ctx.push() #推送上下文信息,即激活上下文
二、请求钩子
有时候,在请求开始或结束后,我们可能想要执行一些代码,比如,在请求开始前,完成数据库的连接,用户信息的认证等等。Flask使用装饰器为我们提供了注册通用函数的功能,支持的钩子函数有以下四种:
before_first_request | 第一次请求之前调用 |
before_request | 每次请求之前调用 |
after_request | 每次请求之后调用,前提是没有未处理的异常抛出 |
teardown_request | 每次请求之后调用,即使有未处理的异常抛出 |
在请求函数和钩子函数之间,一般通过全局变量g实现数据共享。
三、响应
Flask的响应一般可包含三个参数,第一个参数指明响应的字符串,第二个参数可指明响应状态码,如200表示响应成功,第三个参数是由header首部组成的字典。我们可以通过make_response()生成一个response对象并设置。
1 #!/usr/bin/env python
2 # encoding: utf-8
3 from flask import Flask
4 from flask import request
5
6 app = Flask(__name__)
7
8
9 @app.route('/')
10 def hello_world():
11 return 'Hello World!'
12
13
14 @app.route("/user/<user_name>")
15 def hello_user(user_name):
16 """
17 动态路由示例
18 :param user_name: 用户名
19 :return:
20 """
21 1/0
22 return "Hello %s" % user_name
23
24
25 @app.route("/context")
26 def get_context():
27 """
28 获取请求的上下文信息
29 :return:
30 """
31 user_agent = request.headers.get("user-agent")
32 return "your user-agent is %s" % user_agent
33
34
35 @app.before_first_request
36 def first_quest():
37 print "run before first request"
38
39
40 @app.before_request
41 def every_request():
42 print "One new request is comming"
43
44
45 @app.after_request
46 def after_r(exception):
47 print "The request has done 1"
48
49 @app.teardown_request
50 def teardown_r(exception):
51 print "The request has done 2"
52
53
54 if __name__ == '__main__':
55 app.run()
上述代码运行后,在浏览器分别请求
http://127.0.0.1:5000/ 输出:
run before first request
One new request is comming
The request has done 1
The request has done 2
http://127.0.0.1:5000/user/patty 输出:
One new request is comming
The request has done 2
变量共享:通过g实现
1 @app.route('/')
2 def hello_world():
3 print g.user
4 return 'Hello World!'
5
6 @app.before_first_request
7 def first_quest():
8 g.user = 'tmp'
9 print "run before first request"