响应 Response
视图函数的返回值会被自动转换为一个响应对象,Flask的转换逻辑如下:
- 如果返回的是一个合法的响应对象,则直接返回。
- 如果返回的是一个字符串,那么
Flask会重新创建一个werkzeug.wrappers.Response对象,Response将该字符串作为主体,状态码为200,MIME类型为text/html,然后返回该Response对象。 - 如果返回的是一个元组,元祖中的数据类型是(response,status,headers)。status值会覆盖默认的200状态码,headers可以是一个列表或者字典,作为额外的消息头。
- 如果以上条件都不满足,
Flask会假设返回值是一个合法的WSGIt应用程序,并通过Response.force_type(rv,request.environ)转换为一个请求对象。
以下将用例子来进行说明:
第一个例子:直接使用Response创建:
from werkzeug.wrappers import Response
@app.route('/about/')
def about():
resp = Response(response='about page',status=200,content_type='text/html;charset=utf-8')
return resp
第二个例子:可以使用make_response函数来创建Response对象,这个方法可以设置额外的数据,比如设置cookie,header信息等:
from flask import make_response
@app.route('/about/')
def about():
return make_response('about page')
第三个例子:通过返回元组的形式:
@app.errorhandler(404)
def not_found():
return 'not found',404
第四个例子:自定义响应。自定义响应必须满足三个条件:
- 必须继承自
Response类。 - 实现类方法
force_type(cls,rv,environ=None)。 - 必须指定
app.response_class为你自定义的Response
以下将用一个例子来进行讲解,Restful API都是通过JSON的形式进行传递,如果你的后台跟前台进行交互,所有的URL都是发送JSON数据,那么此时你可以自定义一个叫做JSONResponse的类来代替Flask自带的Response类:
from flask import Flask,jsonify
from werkzeug.wrappers import Response
app = Flask(__name__)
class JSONResponse(Response):
default_mimetype = 'application/json'
@classmethod
def force_type(cls,response,environ=None):
if isinstance(response,dict):
response = jsonify(response)
return super(JSONResponse,cls).force_type(response,environ)
app.response_class = JSONResponse
@app.route('/about/')
def about():
return {"message":"about page"}
if __name__ == '__main__':
app.run(host='0.0.0.0',port=8000)
此时如果你访问/about/这个URL,那么在页面中将会显示:
{
"message": "about page"
}
注意以上例子,如果不写app.response_class = JSONResponse,将不能正确的将字典返回给客户端。因为字典不在Flask的响应类型支持范围中,那么将调用app.response_class这个属性的force_type类方法,而app.response_class的默认值为Response,因此会调用Response.force_class()这个类方法,他有一个默认的算法转换成字符串,但是这个算法不能满足我们的需求。因此,我们要设置app.response_class=JSONResponse,然后重写JSONResponse中的force_type类方法,在这个方法中将字典转换成JSON格式的字符串后再返回。
from flask import Flask,Response,jsonify,render_template
# flask = werkzeug+sqlalchemy+jinja2
import json
app = Flask(__name__)
# 将视图函数中返回的字典,转换成json对象,然后返回
# restful-api
class JSONResponse(Response):
@classmethod
def force_type(cls, response, environ=None):
"""
这个方法只有视图函数返回非字符、非元组、非Response对象
才会调用
response:视图函数的返回值
"""
if isinstance(response,dict):
# jsonify除了将字典转换成json对象,还将改对象包装成了一个Response对象
response = jsonify(response)
return super(JSONResponse, cls).force_type(response,environ)
app.response_class = JSONResponse
@app.route('/')
def hello_world():
# Response('Hello World!',status=200,mimetype='text/html')
return 'Hello World!'
@app.route('/list1/')
def list1():
resp = Response('list1')
resp.set_cookie('country','china')
return resp
@app.route('/list2/')
def list2():
return 'list2',200,{'X-NAME':'zhiliao'}
@app.route('/list3/')
def list3():
return {'username':'zhiliao','age':18}
if __name__ == '__main__':
app.run(debug=True,port=8000)







网友评论