一、程序上下文

     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"