6.Flask:重定向和错误响应

Flask(重定向和错误响应 六)

redirect(重定向)实现方式

1
2
3
4
5
6
7
from flask imports redirect

@app.route('/')
def index():
if request.args.get('username') is None:
return redirect('login')
return 'hello'

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def redirect(location, code=302, Response=None):
if Response is None:
from .wrappers import Response

display_location = escape(location)
if isinstance(location, text_type):
from .urls import iri_to_uri

location = iri_to_uri(location, safe_conversion=True)
response = Response(
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n'
"<title>Redirecting...</title>\n"
"<h1>Redirecting...</h1>\n"
"<p>You should be redirected automatically to target URL: "
'<a href="%s">%s</a>. If not click the link.'
% (escape(location), display_location),
code,
mimetype="text/html",
)
response.headers["Location"] = location
return response
  • 重定向的code默认为302
  • 我们传入的第一个参数location被放入到了response.headers["Location"]

浏览器处理工作:

  1. 先判断返回状态码是否为「30x」
  2. 查看返回的头信息中是否有Location字段,如果有则访问新的网址

重定向的两种方式

redirect(‘/new/url’)

不建议使用:url地址可能会发生变更,函数名变更比较少

redirect(url_for(‘endpoint’))

1
2
3
4
5
6
7
8
9
10
@app.route('/')
def index():
if request.args.get('username') is None:
return redirect(url_for('login'))
return 'hello'


@app.route('/login')
def login():
return 'login'

url_for

  1. 生成静态文件
1
url_for('static',filename='style.css')

例子:

1
2
3
4
5
6
7
8
9
10
11
12
from flask import Flask, render_template

app = Flask(__name__, static_url_path='/src')


@app.route('/')
def index():
return render_template('index.html')


if __name__ == '__main__':
app.run()

templates/index.html

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="{{ url_for('static',filename='css/demo.css') }}">
<title>Title</title>
</head>
<body>
<p>hello</p>
</body>
</html>

static/css/demo.css

1
2
3
.p {
color: red;
}

css_url

http://127.0.0.1:5000/src/css/demo.css可以看出,这个url变成了static_url_path替换部分

  1. 跳转的时候添加参数
1
2
3
4
5
6
7
8
9
10
@app.route('/')
def index():
if request.args.get('username') is None:
return redirect(url_for('login', username='zhongxin'))
return 'hello'


@app.route('/login', endpoint='login')
def login():
return 'login'

访问:http://127.0.0.1:5000/

会跳转到:http://127.0.0.1:5000/login?username=zhongxin

url_for带参数跳转

错误响应

没有任何处理的错误返回

1
2
3
4
5
6
7
8
9
10
11
12
13
from flask import Flask, render_template

app = Flask(__name__, static_url_path='/src')


@app.route('/')
def index():
1 / 0
return render_template('index.html')


if __name__ == '__main__':
app.run()

未处理

处理500错误

1
2
3
@app.errorhandler(500)
def server_error(error):
return '我们正在升级'

错误返回

使用官网定义的错误返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from flask import Flask, render_template, request, abort

app = Flask(__name__, static_url_path='/src')


@app.route('/')
def index():
if not request.args.get('username'):
abort(401)
return render_template('index.html')


if __name__ == '__main__':
app.run()

官网定义的401

使用自己的html定义错误返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from flask import Flask, render_template, request, abort, make_response

app = Flask(__name__, static_url_path='/src')


@app.route('/')
def index():
if not request.args.get('username'):
abort(make_response(render_template('user_error_404.html'), 404))
return render_template('index.html')


if __name__ == '__main__':
app.run()

自己的html定义错误返回

重写官方的404错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from flask import Flask, render_template, request, abort, make_response

app = Flask(__name__, static_url_path='/src')


@app.errorhandler(404)
def server_error(error):
return render_template('user_error_404.html')


@app.route('/')
def index():
if not request.args.get('username'):
abort(404)
return render_template('index.html')


if __name__ == '__main__':
app.run()

abort源码

1
2
3
4
5
def abort(status, *args, **kwargs):
return _aborter(status, *args, **kwargs)


_aborter = Aborter()

其实就是调用Aborter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Aborter(object):
def __init__(self, mapping=None, extra=None):
if mapping is None:
mapping = default_exceptions
self.mapping = dict(mapping)
if extra is not None:
self.mapping.update(extra)

def __call__(self, code, *args, **kwargs):
if not args and not kwargs and not isinstance(code, integer_types):
raise HTTPException(response=code)
if code not in self.mapping:
raise LookupError("no exception for %r" % code)
raise self.mapping[code](*args, **kwargs)

执行的时候就是__call__会抛出异常

其实,它就是抛出一个异常而已

自己创建错误信息类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from flask import Flask, render_template, request

app = Flask(__name__, static_url_path='/src')


class UserError(Exception):
pass


@app.errorhandler(UserError)
def server_error(error):
return render_template('user_error_404.html', error=error)


@app.route('/')
def index():
if not request.args.get('username'):
raise UserError()
return render_template('index.html')


if __name__ == '__main__':
app.run()
 wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
您的支持将鼓励我继续创作!