一、程序上下文
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"