最新版的hello.py 存在一个可用性问题。用户输入名字后提交表单,然后点击浏览器的刷新按钮,会看到一个莫名其妙的警告,要求在再次提交表单之前进行确认。之所以出现这种情况,是因为刷新页面时浏览器会重新发送之前已经发送过的最后一个请求。如果这个
请求是一个包含表单数据的POST 请求,刷新页面后会再次提交表单。大多数情况下,这并不是理想的处理方式。

  很多用户都不理解浏览器发出的这个警告。基于这个原因,最好别让Web 程序把POST 请求作为浏览器发送的最后一个请求。

  这种需求的实现方式是,使用重定向作为POST 请求的响应,而不是使用常规响应。重定向是一种特殊的响应,响应内容是URL,而不是包含HTML 代码的字符串。浏览器收到这种响应时,会向重定向的URL 发起GET 请求,显示页面的内容。这个页面的加载可能要多花几微秒,因为要先把第二个请求发给服务器。除此之外,用户不会察觉到有什么不同。现在,最后一个请求是GET 请求,所以刷新命令能像预期的那样正常使用了。这个技巧称为Post/ 重定向/Get 模式。

  但这种方法会带来另一个问题。程序处理POST 请求时,使用form.name.data 获取用户输入的名字,可是一旦这个请求结束,数据也就丢失了。因为这个POST 请求使用重定向处理,所以程序需要保存输入的名字,这样重定向后的请求才能获得并使用这个名字,从而构建真正的响应。

  程序可以把数据存储在用户会话中,在请求之间“记住”数据。用户会话是一种私有存储,存在于每个连接到服务器的客户端中。它是请求上下文中的变量,名为session,像标准的Python 字典一样操作。

  默认情况下,用户会话保存在客户端cookie 中,使用设置的SECRET_KEY 进行加密签名。如果篡改了cookie 中的内容,签名就会失效,会话也会随之失效。

  下面的例子是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'))

  在程序的前一个版本中,局部变量name 被用于存储用户在表单中输入的名字。这个变量现在保存在用户会话中,即session['name'],所以在两次请求之间也能记住输入的值。

  现在,包含合法表单数据的请求最后会调用redirect() 函数。redirect() 是个辅助函数,用来生成HTTP 重定向响应。redirect() 函数的参数是重定向的URL,这里使用的重定向URL 是程序的根地址,因此重定向响应本可以写得更简单一些,写成redirect('/'),但却会使用Flask 提供的URL 生成函数url_for()。推荐使用url_for() 生成URL,因为这个函数使用URL 映射生成URL,从而保证URL 和定义的路由兼容,而且修改路由名字后依然可用。

  url_for() 函数的第一个且唯一必须指定的参数是端点名,即路由的内部名字。默认情况下,路由的端点是相应视图函数的名字。在这个示例中,处理根地址的视图函数是index(),因此传给url_for() 函数的名字是index。

  最后一处改动位于render_function() 函数中,使用session.get('name') 直接从会话中读取name 参数的值。和普通的字典一样,这里使用get() 获取字典中键对应的值以避免未找到键的异常情况,因为对于不存在的键,get() 会返回默认值None。使用这个版本的程序时,刷新浏览器页面,你看到的新页面就和预期一样了。

Flask从入门到精通之重定向和用户会话的更多相关文章

  1. Flask从入门到精通之flask程序入门

    初始化 所有Flask程序都必须创建一个程序实例,Web服务器使用一种名为Web服务器网关接口的的协议(WSGI),把接收自客户端的所有请求转发给这个对象处理.程序实例是Flask类的对象,使用下面代 ...

  2. Flask从入门到精通之Flash消息

    请求完成后,有时需要让用户知道状态发生了变化.这里可以使用确认消息.警告或者错误提醒.一个典型例子是,用户提交了有一项错误的登录表单后,服务器发回的响应重新渲染了登录表单,并在表单上面显示一个消息,提 ...

  3. 安全性测试入门 (四):Session Hijacking 用户会话劫持的攻击和防御

    本篇继续对于安全性测试话题,结合DVWA进行研习. Session Hijacking用户会话劫持 1. Session和Cookies 这篇严格来说是用户会话劫持诸多情况中的一种,通过会话标识规则来 ...

  4. Flask从入门到精通之大型程序的结构二

    一.程序包 程序包用来保存程序的所有代码.模板和静态文件.我们可以把这个包直接称为app(应用),如果有需求,也可使用一个程序专用名字.templates 和static 文件夹是程序包的一部分,因此 ...

  5. Flask从入门到精通之使用Flask-SQLAlchemy管理数据库

    Flask-SQLAlchemy 是一个Flask 扩展,简化了在Flask 程序中使用SQLAlchemy 的操作.SQLAlchemy 是一个很强大的关系型数据库框架,支持多种数据库后台.SQLA ...

  6. Flask从入门到精通之在视图函数中处理表单

    在新版hello.py 中,视图函数index() 不仅要渲染表单,还要接收表单中的数据.更新后的index() 视图函数如下: @app.route('/') def index(): name = ...

  7. Flask从入门到精通之Flask表单

    Flask请求对象包含客户端发出的所有请求信息.其中,request.form 能获取POST 请求中提交的表单数据.尽管Flask 的请求对象提供的信息足够用于处理Web 表单,但有些任务很单调,而 ...

  8. Flask从入门到精通之Flask-Bootstrap的使用

    Bootstrap(http://getbootstrap.com/)是Twitter 开发的一个开源框架,它提供的用户界面组件可用于创建整洁且具有吸引力的网页,而且这些网页还能兼容所有现代Web 浏 ...

  9. Flask从入门到精通之flask扩展

    Flask被设计成可扩展形式,因此并没有提供一些重要的功能,比如数据库和用户认证,所以开发者可以自由选择最适合程序的包,或者按需求自行开发.社区成员开发了大量不同用途的扩展,如果这还不能满足需求,你还 ...

随机推荐

  1. Jmeter获取不到cookie(备注:前面和后面的几个步骤都可以获取到cookie)

    今天的一个Jmeter脚本,有一个HTTP request始终获取不到cookie,但其前面和后面的几个步骤都可以获取到cookie,报文的请求服务器地址都是照着fiddler上面填的,没有问题,后来 ...

  2. dwr 框架 ,实现 ajax 的java 框架

    1. 引入 dwr.jar 包 2. 配置web.xml 文件 ,拦截请求 <servlet> <servlet-name>dwr-invoker</servlet-na ...

  3. Angular 通过注入 $location 获取与修改当前页面URL

    //1.获取当前完整的url路径 var absurl = $location.absUrl(); //http://172.16.0.88:8100/#/homePage?id=10&a=1 ...

  4. Servlet的Cookie值保存与获取

    今天测试设置和获取Cookie遇到了一点小问题,很奇怪的问题:把J2ee服务部署在本地 8080端口:访问任何一个服务时,如果客户端没有cookie,则下发cookie, 如果客户端已经有了该cook ...

  5. 字典树Java实现

    Trie树的原理 Trie树也称字典树,因为其效率很高,所以在在字符串查找.前缀匹配等中应用很广泛,其高效率是以空间为代价的. 利用串构建一个字典树,这个字典树保存了串的公共前缀信息,因此可以降低查询 ...

  6. 进度条ProgressBar

    在本节中,作者只写出了进度条的各种样式,包括圆形.条形,还有自定义的条形,我想如果能让条形进度条走满后再继续从零开始,于是我加入了一个条件语句.作者的代码中需要学习的是handler在主线程和子线程中 ...

  7. linux上安装tomcat

    这里采用离线解压tar.gz的方式安装 下载: wget http://mirror.bit.edu.cn/apache/tomcat/tomcat-8/v8.0.33/bin/apache-tomc ...

  8. JAVA中的内联函数

    在说内联函数之前,先说说函数的调用过程. 调用某个函数实际上将程序执行顺序转移到该函数所存放在内存中某个地址,将函数的程序内容执行完后,再返回到 转去执行该函数前的地方.这种转移操作要求在转去前要保护 ...

  9. HDU1065 I Think I Need a Houseboat 2016-07-24 13:59 101人阅读 评论(0) 收藏

    I Think I Need a Houseboat Problem Description Fred Mapper is considering purchasing some land in Lo ...

  10. jersey学习笔记

    最近一个项目用到了jersey,我只是负责前端.也借此机会好好了解一下REST webservice及一大推名词. http://redhacker.iteye.com/blog/1914105 1. ...