1.重定向和用户会话
在web表单(1)中的hello.py存在一个问题:用户输入名字提交表单后,点击浏览器的刷新按钮,会得到一个要求用户再次提交表单之前进行确认的警告。出现这个问题的原因是刷新页面时浏览器会重新发送之前已经发送过的最后一个请求。如果这个请求是包含表单数据的POST请求,刷新页面后会再次提交表单。所以要解决这个问题,最好的办法是别让web程序把POST请求作为浏览器发送的最后一个请求。
这个问题解决的实现方式是使用重定向作为POST请求的响应。
重定向:是一种特殊的响应,响应内容是URL,而不是包含HTML代码的字符串。浏览器收到这种响应时,会向重定向的URL发起GET请求。这个技巧称为POST/重定向/GET模式。
重定向会带来一个问题:程序处理POST请求时,使用form.name.data获取用户输入的名字,可是一旦请求结束了,数据也就丢失了,所以程序需要保存这个名字,这样重定向后的请求才能获得和使用这个名字。
程序可以把数据存储在用户会话中。
用户会话:是一种私有存储,存在于每个连接到服务器的客户端中。默认情况下,用户会话保存在客户端的cookie中,使用设置的SECRET_KEY进行加密签名。
hello.py完整代码:
redirect():是一个辅助函数,用来生成HTTP重定向。参数是重定向的URL。from flask import Flask from flask import render_template,session,redirect,url_for from flask_wtf import Form from wtforms import StringField, SubmitField from wtforms.validators import Required from flask_bootstrap import Bootstrap app = Flask(__name__) bootstrap = Bootstrap(app) app.config['SECRET_KEY'] = 'yangdidi' class NameForm(Form): name = StringField('What is your name ?',validators=[Required()]) submit = SubmitField('Submit')@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'))app.run(debug=True)
url_for():第一个且唯一必须指定的参数是端点名,即路由的内部名字。默认情况下,路由的端点是响应视图函数的名字。
2.Flash消息:Flask的核心特性
请求完成时,需要让用户知道请求的结果,可以给用户发送确认消息、警告或者错误提醒来通知用户。flash()函数可以实现这种效果。
要完成这个功能,需要在hello.py和base.html都要加入flash相关的内容。
hello.py:falsh消息
from flask import Flask from flask import render_template,session,redirect,url_for,flash from flask_wtf import Form from wtforms import StringField, SubmitField from wtforms.validators import Required from flask_bootstrap import Bootstrap app = Flask(__name__) bootstrap = Bootstrap(app) app.config['SECRET_KEY'] = 'yangdidi' class NameForm(Form): name = StringField('What is your name ?',validators=[Required()]) submit = SubmitField('Submit')
@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 return redirect(url_for("index")) return render_template("index.html", form=form, name=session.get('name')) app.run(debug=True)
在这个py文件中,每次提交的名字都会和前一次提交的进行比较,若不同于前一次提交的名字,就会调用falsh()函数,发给用户一个提示消息。
仅仅使用flash()函数调用是不能实现把这个消息发送到页面显示给用户的,还需要模板渲染这个消息。最好的方式是在基模板中渲染,这样就可以在任意页面上使用这个功能。
Flask开发get_flashed_messages()函数给模板,用来获取并渲染消息。
templates/base.html:渲染flash消息
渲染后的结果图如下:{% 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 %}