更多内容,请关注微信公众号:tmac_lover
使用flask编写web应用程序时很重要的一个工作就是路由的视图函数编写。对于刚接触flask的人来说,有时候会觉得很奇怪,为什么路由的视图函数返回值有好几种写法,今天总结一下视图函数返回值的种类,并简要分析一下,这几种返回值的本质,以及它们最终是如何返回给流览器的。
先列出常见的几种flask视图函数返回值的形式:
@app.route('/test')
def test():
return 'hello world!'
@app.route('/test')
def test():
return render_template('index.html')
@app.route('/test')
def test():
return jsonify({'name': 'tom'})
@app.route('/test')
def test():
# 返回元组时,顺序依次是:返回内容,返回状态码,返回的header
return 'hello world', 200, {'Locateion':'www.baidu.com'}
# 也可以使用jsonify返回元组
# return jsonify({}), 200, {'Locateion':'www.baidu.com'}
@app.route('/test')
def test():
response = make_response('hello')
response.headers = {'Location':'abc'}
return response
基本上常见的就是以上几种形式,看上去是不是有些眼花缭乱?其实在了解了flask里视图函数的返回值是如何被组装处理的,那就不会感到凌乱,并且会有助于记忆。
实际上,flask是基于Werkzeug工具包的一个web服务框架,所以flask里视图函数的实现,实际上是对werkzeug的一层封装,我们先看一下一个简单的werkzeug应用是怎么实现的:
from werkzeug.wrappers import Request, Response
def application(environ, start_response):
request = Request(environ)
text = 'Hello %s!' % request.args.get('name', 'World')
response = Response(text, mimetype='text/plain')
return response(environ, start_response)
可以看到,实际上werkzeug要求每次请求的返回值是Response类型。所以实际上,flask的视图函数返回值无论如何变,它都不会离开Response类型。
flask视图函数调用过程如下:
rv = full_dispatch_request() [class Flask]
-> dispatch_request() [class Flask]
-> self.view_functions[rule.endpoint](**req.view_args)
finalize_request(rv)
-> make_response(rv) [class Flask]
-> rv = self.response_class(rv, status=status, headers=headers) [class Flask]
# 这里response_class实际上就是Response类
return rv
可以看到,无论flask里视图函数的返回值是什么样式,最终都会调用Flask.make_response()里的response_class构造一个Response对象。回头看flask视图函数的返回值:
在Flask.make_response()里,会根据视图函数返回的值的个数,类型的不同,来做不同的处理,生成最终的Response对象,并为字添加code和header等。
无论如何,看源码,是最有效的学习方法。