如果在执行后端代码的时候,用户的访问不能满足你规定的要求的时候,你还想给用户一个反馈,这里就可以使用abort函数,立即终止视图函数的执行,并返回给前端特定的信息
例如这里我们模拟,用户访问首页的时候,需要先登录,跳转到登录页面后,模拟用户输入的请求是错误,我们返回给他401的状态(禁止访问)
# coding:utf-8 from flask import Flask, redirect, url_for, abort # 这里我们需要导入abort这个类 app = Flask(__name__) @app.route('/') def index(): # 将视图重定向到login页面 return redirect(url_for('login')) def this_is_never_excuted(): # 永远不会被执行 pass @app.route("/login", methods=['GET']) def login(): # 模拟登陆失败, 返回401意为着禁止访问 abort(401) print('永远不会去执行') this_is_never_excuted() if __name__ == '__main__': app.run(host='0.0.0.0', debug=True)
返回结果:
这里可以看出返回的状态码是401说明,我们abort函数执行了,通过后台返回的信息也能看出,abort函数之后的代码也没有执行,下面就是服务端的返回信息:
(Flask_py) python@python-VirtualBox:~/code$ python abort_demo.py * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 294-731-034 192.168.3.5 - - [23/Jul/2019 07:41:58] "GET / HTTP/1.1" 302 - 192.168.3.5 - - [23/Jul/2019 07:41:58] "GET /login HTTP/1.1" 401 - 192.168.3.5 - - [23/Jul/2019 07:41:58] "GET /favicon.ico HTTP/1.1" 404 -
通过源码我们可以看到abort函数给出的注释里还有一种应用方法
''' Can be passed a WSGI application or a status code. If a status code is given it's looked up in the list of exceptions and will raise that exception, if passed a WSGI application it will wrap it in a proxy WSGI exception and raise that:: abort(404) abort(Response('Hello World')) '''
大概翻译的就是:
你可以传递一个WSGI应用或者是一个状态码。如果给定一个状态码,它会在异常列表中查找并引发异常,如果传递的是一个WSGI应用,它将把它包装在一个代理WSGI异常中并引发该异常
# abort 的另一种应用方法 from flask import Flask, redirect, url_for, abort, Response # 需要导入的包 app = Flask(__name__) @app.route('/') def index(): # 将视图重定向到login页面 return redirect(url_for('login')) def this_is_never_excuted(): # 永远不会被执行 pass @app.route("/login", methods=['GET']) def login(): # 模拟登陆失败, 返回401意为着禁止访问 # abort(401) abort(Response('禁止访问!!!')) print('永远不会去执行') this_is_never_excuted() if __name__ == '__main__': app.run(host='0.0.0.0', debug=True)
这里并不是抛出状态码给定的HTTPException,所以浏览器默认认为,它只是执行了, 我们想给定的结果,所以状态码是200,现在我们使用到的都是默认给出的状态码返回的信息,比如页面未找到会抛出一个404的状态码。如果你要定制错误页面,这里就可以使用errorhandler() 装饰器:
# coding:utf-8 from flask import Flask, redirect, url_for, abort, Response app = Flask(__name__) @app.route('/') def index(): # 将视图重定向到login页面 return redirect(url_for('login')) def this_is_never_excuted(): # 永远不会被执行 pass @app.route("/login", methods=['GET']) def login(): # 模拟登陆失败, 返回401意为着禁止访问 abort(404) # abort(Response('禁止访问!!!')) # print('永远不会去执行') # this_is_never_excuted() # 自定义错误视图,用来返回给前端用户看到的结果 @app.errorhandler(404) def page_not_found(error): return "页面未找到 %s" % error, 404 if __name__ == '__main__': app.run(host='0.0.0.0', debug=True)
访问127.0.0.1:5000/ 会返回的结果是:因为这里跳转到登录页面之后会直接执行abort(404)
这就是通过我们自己定制给出的返回结果
响应
视图函数的返回值会被自动转换为一个响应对象。如果返回值是一个字符串, 它被转换为该字符串为主体的、状态码为 200 OK``的 、 MIME 类型是 ``text/html 的响应对象。Flask 把返回值转换为响应对象的逻辑是这样:
-
如果返回的是一个合法的响应对象,它会从视图直接返回。
-
如果返回的是一个字符串,响应对象会用字符串数据和默认参数创建。
-
如果返回的是一个元组,且元组中的元素可以提供额外的信息。这样的元组必须是 (response, status, headers) 的形式,且至少包含一个元素。 status 值会覆盖状态代码, headers 可以是一个列表或字典,作为额外的消息标头值。
-
如果上述条件均不满足, Flask 会假设返回值是一个合法的 WSGI 应用程序,并转换为一个请求对象。
如果你想在视图里操纵上述步骤结果的响应对象,可以使用 make_response() 函数。
接下来定义一个index视图,分别展示一下返回响应的信息和自定义的状态码
# coding:utf-8 from flask import Flask, make_response app = Flask(__name__) @app.route("/index") def index(): # 1 使用元祖,返回自定义的响应信息 # 响应体 状态码 响应头 # return "index page", 400, [("Programme_L", "python"), ("Locality", "Harbin")] # return "index page", 400, {"Programme_L": "python", "Locality": "Harbin"} # return "index page", "666 userDefined status", {"Programme_L": "python", "Locality": "Harbin"} # return "index page", "666 userDefined status" # 2 使用make_response 响应信息 resp = make_response("index page 2") resp.status = "999 userDefined" # 设置状态码 resp.headers["city"] = "Harbin" # 设置响应头 return resp if __name__ == '__main__': app.run(host='0.0.0.0', debug=True)
这里只给大家展示用make_response 响应的结果:
返回 json 数据
在学习Python的时,其中有一个json模块可以帮我们将字典数据转换成 json字符串【json.dumps(dict)】,也可以将字符串转换成Python中的字典【json.loads(str)】,显然我们这里就可以这样使用
# coding:utf-8 import json from flask import Flask app = Flask(__name__) @app.route("/index") def index(): data = { 'name': 'circle', 'age': 30, } json_str = json.dumps(data) return json_str, 200, {"Content-Type": "application/json"} # 这里我们一定要手动添加这句话来指定为json数据 if __name__ == '__main__': app.run(host='0.0.0.0', debug=True)
虽然我们这样自己指定也是很方便的就可以将json数据返回,但是我们还是需要手动添加{"Content-Type": "application/json"} 来指定为json数据,这里我们使用Flask框架帮我封装的 jsonify() 就可以完成更简便的操作
# coding:utf-8 from flask import Flask, jsonify app = Flask(__name__) @app.route("/index") def index(): data = { 'name': 'circle', 'age': 30, } # json_str = json.dumps(data) # return json_str, 200, {"Content-Type": "application/json"} return jsonify(data) if __name__ == '__main__': app.run(host='0.0.0.0', debug=True)