首页 > 代码库 > FlaskWebDevelopment - 表单的处理2- 重定向&用户session&提示信息

FlaskWebDevelopment - 表单的处理2- 重定向&用户session&提示信息

重定向(Redirects)和用户Session

目前我们写的这个hello.py有个易用性的问题。如果你输入name并提交,之后再点刷新按钮,那么浏览器可能弹出一个莫名其表的告警,要求你确认是否重新发送表单数据,其实你什么都没做。这是因为浏览器的刷新操作实际上是重复最后一次发送的请求,这种情况下最后一次请求就是发送带有表单数据的POST请求。显然大家都不想要这种效果。

许多用户不理解浏览器弹出的这个告警。因此,对web应用来说的一个最佳实践就是:永远不要让POST请求成为浏览器的最后一个请求。

这个实践可以通过利用redirect来响应POST请求来实现。重定向是一种特殊的response,他的内容是一个URL而不是一个HTML的字符串。浏览器收到这种响应后,会向这个URL发出一个GET请求,然后这个页面就显示出来了。这种情况下,因为发送了两次requset,耗时稍长,但体验上影响不大。现在,最后一个请求是GET了,如果刷新也不会有什么告警。这个技巧被称为 Post/Redirect/Get 模式。

好吧,这里其实又引发另一个问题。当应用处理POST请求,把表单数据保存到视图函数的name变量里,这个变量的值在函数退出后就没了。现在POST的响应是个重定向,那么就需要把这个值保存下来。

应用可以利用 * user session来保存requset之间的数据,这个存储是对每个连接的用户私有的。这个user session是之前的requset上下文里提到的(这还是个坑,没填了*)。操作方式跟字典类似。

注:默认情况下,session都是保存在client端的cookies里,并且通过之前配置的SECRET_KEY加密签名过的。任何试图篡改其内容的都会导致签名失败,最终使session失效

来看重定向版本的index()

from flask import Flask, render_template, session, redirect, url_for
@app.route(‘/‘, methods=[‘GET‘, ‘POST‘])
def index():
    form = NameForm()
    if form.validate_on_submit():
        session[‘name‘] = form.name.data
        return redirect(url_for(‘index‘))
    return render_template(‘index.html‘, form=form, name=session.get(‘name‘))

注:代码 4b tag

之前用一个临时变量name来保存的数据,现在修改为放在session中,这样就可以在requset之间保存住数据。

现在函数在有数据情况下返回的就是重定向响应,通过redirect()方法来实现。这个方法的入参是要重定向到的URL,这里用的是url_for()函数,这个函数之前在模板里讲过,自动根据输入的视图函数名生成URL。直接写个redirect(‘/‘)在这里效果是一样的,但是不推荐。

‘url_for()‘只接受一个参数,就是路由端点名称,默认情况下一条路由的端点名就是视图函数名,所以上面写的就是index

现在的网页工作就正常了。

信息提示

有时候需要给用户一些提示信息,报错告警之类的。比如用户登陆时候填错密码,就有消息提示用户名或密码错误。

Flask框架把这个功能作为核心功能内置。flash()方法用来做这个事。

显示消息的例子:

from flask import Flask, render_template, session, redirect, url_for, flash
@app.route(‘/‘, methods=[‘GET‘, ‘POST‘])
def index():
    form = NameForm()
    if form.validate_on_submit():
        old_name = session.get(‘name‘)
        if old_name is not None and old_name != form.name.data:
            flash(‘Looks like you have changed your name!‘)
        session[‘name‘] = form.name.data
        form.name.data = http://www.mamicode.com/‘‘> 

还是hello.py,这里我们增加了一个flash()使用。当用户两次提交不同名字的时候,我们的响应里,就多了一条提示消息。

只在代码里调用flash()当然不能把消息显示出来,模板也需要修改。这个修改最好放到基础模板里做,这样所有子模板就都不需要改动了。在模板里可以通过get_flashed_messages()方法接收消息的内容。

还是例子,基础模板templates/base.html:

{% block content %}
<div class="container">
    {% for message in get_flashed_messages() %}
    <div class="alert alert-warning">
        <button type="button" class="close" data-dismiss="alert">&times;</button>
        {{ message }}
    </div>
    {% endfor %}
    {% block page_content %}{% endblock %}
</div>
{% endblock %}

注: 代码 4c tag
上面用了模板引擎支持的循环结构,每次在代码里调用flash(),在get_flashed_messages()时就多一个记录,且这个记录在提取出来之后就不能在获取了。渲染时利用了Bootstrap的alert CSS样式。效果图:

1

下节开始就是数据库了。

FlaskWebDevelopment - 表单的处理2- 重定向&用户session&提示信息