vlambda博客
学习文章列表

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

redirect(重定向)实现方式

from flask imports redirect

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

源码

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')

redirect(url_for('endpoint'))

@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. 生成静态文件

url_for('static',filename='style.css')

例子:

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

<!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

.p {
    color: red;
}
css_url

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

  1. 跳转的时候添加参数

@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

Flask(重定向和错误响应 六)
url_for带参数跳转

错误响应

没有任何处理的错误返回

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()
Flask(重定向和错误响应 六)
未处理

处理500错误

@app.errorhandler(500)
def server_error(error):
    return '我们正在升级'
Flask(重定向和错误响应 六)
错误返回

使用官网定义的错误返回

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定义错误返回

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错误

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源码

def abort(status, *args, **kwargs):
    return _aborter(status, *args, **kwargs)


_aborter = Aborter()

其实就是调用Aborter

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__会抛出异常

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

自己创建错误信息类

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()