出现的问题:
用户提交表单后,在刷新浏览器,会有上图的一个提醒
出现原因:
刷新浏览器会重新发送之前发送的最后一个请求,若该请求是一个包含表单数据的post请求,刷新浏览器后会再次提交表单
解决方法:
不讲web程序发送的POST请求最为浏览器发送的最后一个请求
需求的实现方式:
不适用常规的响应,使用重定向作为POST请求的响应
重定向
是一种特殊的响应方式,响应的内容是url,不是包含HTML代码的字符串,
浏览器收到这种响应后,会向重定向的url发起GET请求,显示页面的内容
现在最后一个请求是get请求
重定向实现中的问题:
程序处理post时,使用form.name.data获取用户输入,但是一旦这个请求结束,数据也丢失了,所以程序需要保存输入的名字,这样重定向请求后才能获取并使用这个名字,从而构建正真的响应
解决问题
将数据从存储在用户会话中,在请求之间记住数据
用户会话
是一种私有存储,存在每个连接到服务器的客户端中,是请求上下文中的变量,名为session,向python字典一样操作。
默认情况下session保存在客户端cookie中,使用设置的SECRET_KEY进行加密,如果篡改了cooki中的内容,签名就会失效,会话随之失效
# -*- coding:utf-8 -*-
from flask import Flask ,render_template,session,redirect,url_for
from flask.ext.script import Manager
from flask_bootstrap import Bootstrap
from flask.ext.moment import Moment
from flask.ext.wtf import Form
from wtforms import StringField,SubmitField
from wtforms.validators import Required
app = Flask(__name__)
app.config['SECRET_KEY']='hard to guess string'
manager = Manager(app)
bootstrap = Bootstrap(app)
moment = Moment(app)
form = Form()
class NameForm(Form):
name = StringField('What is your name?',validators = [Required()])
submit = SubmitField('Submit')
#主页
@app.route('/')
def index():
name = None
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.route('/user/<name>')
def user(name):
return render_template('user.html',name = name )
# 404 error
@app.errorhandler(404)
def page_not_found(e):
#错误处理程序也会返回响应,包括返回与错误对应的数字状态码
return render_template('404.html'),404
#500 error
@app.errorhandler(500)
def internal_server_error(e):
return render_template('500.html'),500
if __name__ == '__main__':
manager.run()
1. name变量
前一个版本,局部变量name用于存储用户在表单中输入的名字,
现在name变量存储在用户会话中,session[‘name’],所以在两次请求之间记住用户输入
2. redirect(url_for(”))
是一个辅助函数,用来生成HTTP重定向响应,
参数:
函数的第一个
重定向的UTL,此处使用url_for(‘inde’)生成url
使用url_for()的原因:
函数使用url映射生成url,保证url和定义的路由兼容,修改路由后依然可以使用
3. url_for()
函数的第一个 参数必须是 端点名,及路由的内部名字
默认情况下端点名是视图函数的名字
使用url_for()的原因:
函数使用url映射生成url,保证url和定义的路由兼容,修改路由后依然可以使用
4. session.get(‘name’)
直接从session会话中读取name参数的值,和普通字典一样,
get()获取字典中键对应的值,对于 不存在的键,get()返回None