首页 > 代码库 > 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">×</button> {{ message }} </div> {% endfor %} {% block page_content %}{% endblock %} </div> {% endblock %}注: 代码 4c tag
上面用了模板引擎支持的循环结构,每次在代码里调用flash()
,在get_flashed_messages()
时就多一个记录,且这个记录在提取出来之后就不能在获取了。渲染时利用了Bootstrap的alert CSS样式。效果图:下节开始就是数据库了。
FlaskWebDevelopment - 表单的处理2- 重定向&用户session&提示信息