flask提供了Response最为视图最终返回的数据,但在代码编写过程中,我们通常很少直接使用Response对象,下面是几个常见的视图返回数据的方式
from flask import Flask, jsonify, render_template, Response
app = Flask(__name__)
@app.route('/text')
def get_text():
return '返回文本'
@app.route('/dict')
def get_dict():
return {'state': 0}
@app.route('/json')
def get_json():
return jsonify({'state': 0})
@app.route('/html')
def get_html():
return render_template('index.html')
@app.route('/response')
def get_resonponse():
return Response('Not Found', status=404)
if __name__ == '__main__':
app.run(port=5566)
使用谷歌浏览器来查看这几个http响应的类型,1, 4, 5 的Content-Type 是 text/html,2,3的Content-Type 是application/json。这说明,flask会根据视图函数的返回值类型,来决定最终的Content-Type。
视图函数的返回值,最终会传递给make_response方法,在该方法中,对返回值的类型进行判断,并根据返回值的不同做相应的处理
def make_response(self, rv):
status = headers = None
# unpack tuple returns
if isinstance(rv, tuple):
len_rv = len(rv)
# a 3-tuple is unpacked directly
if len_rv == 3:
rv, status, headers = rv
# decide if a 2-tuple has status or headers
elif len_rv == 2:
if isinstance(rv[1], (Headers, dict, tuple, list)):
rv, headers = rv
else:
rv, status = rv
# other sized tuples are not allowed
else:
raise TypeError(
"The view function did not return a valid response tuple."
" The tuple must have the form (body, status, headers),"
" (body, status), or (body, headers)."
)
# the body must not be None
if rv is None:
raise TypeError(
"The view function did not return a valid response. The"
" function either returned None or ended without a return"
" statement."
)
# make sure the body is an instance of the response class
if not isinstance(rv, self.response_class):
if isinstance(rv, (text_type, bytes, bytearray)):
# let the response class set the status and headers instead of
# waiting to do it manually, so that the class can handle any
# special logic
rv = self.response_class(rv, status=status, headers=headers)
status = headers = None
elif isinstance(rv, dict):
rv = jsonify(rv)
elif isinstance(rv, BaseResponse) or callable(rv):
# evaluate a WSGI callable, or coerce a different response
# class to the correct type
try:
rv = self.response_class.force_type(rv, request.environ)
except TypeError as e:
new_error = TypeError(
"{e}\nThe view function did not return a valid"
" response. The return type must be a string, dict, tuple,"
" Response instance, or WSGI callable, but it was a"
" {rv.__class__.__name__}.".format(e=e, rv=rv)
)
reraise(TypeError, new_error, sys.exc_info()[2])
else:
raise TypeError(
"The view function did not return a valid"
" response. The return type must be a string, dict, tuple,"
" Response instance, or WSGI callable, but it was a"
" {rv.__class__.__name__}.".format(rv=rv)
)
# prefer the status if it was provided
if status is not None:
if isinstance(status, (text_type, bytes, bytearray)):
rv.status = status
else:
rv.status_code = status
# extend existing headers with provided headers
if headers:
rv.headers.extend(headers)
return rv
从上面的代码中可以看到,当视图返回一个字典时,flask会自动使用jsonify进行转换。通常情况下,我们不会在视图中直接返回Response对象,因为make_response会帮我们将返回值封装成Response。但如果你自己相对返回值进行特殊处理,那么直接返回Response对象是可行的,就像get_resonponse函数那样操作。
如果你的一个接口需要返回图片数据,那么就可以直接构造Response对象
@app.route("/image")
def image():
f = open("static/public/pic/coolpython.png", 'rb')
resp = Response(f.read(), mimetype="image/jpeg")
return resp
如果不直接创建Response对象,那么你就无法设置mimetype首部
你还可以自己定义一个Response类,做一些个性化的处理,但这个类必须继承Response
class ImageResponse(Response):
default_mimetype = 'image/jpeg'
@app.route("/image")
def image():
f = open("static/public/pic/coolpython.png", 'rb')
resp = ImageResponse(f.read())
return resp
我自定义的ImageResponse类里,default_mimetype 就是image/jpeg, 因此在视图中创建ImageResponse对象时无需再设置mimetype。
flask对象有一个response_class属性,默认是Response,你可以将其替换成自定义的响应类,假设你要实现一个图片服务,返回的数据都是图片,mimetype都是image/jpeg,那么你可以这样做
class ImageResponse(Response):
default_mimetype = 'image/jpeg'
app = Flask(__name__)
app.response_class = ImageResponse
@app.route("/image")
def image():
f = open("static/public/pic/coolpython.png", 'rb')
return f.read()
在image函数,直接返回从图片中读取的数据返回,这些数据最终会被ImageResponse类处理
QQ交流群: 211426309