Flask学习笔记(三) 表单

所谓表单,没找到准确定义。大致上可以理解为服务器创建表单供用户填写数据,填好后浏览器向服务器发送表单数据。

表单数据由 Web 浏览器提交给服务器,这一过程通常使用 POST 请求。

Flask-WTF 扩展可以把处理 Web 表单的过程变成一种愉悦的体验。这个扩展对独立的 WTForms 包进行了包装,方便集成到 Flask 应用中。 Flask-WTF 及其依赖可使用 pip 安装: pip install flask-wtf

特殊的一点是,Flask-WTF 无须在应用层初始化,但是它要求应用配置一个密钥

app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string 23333'

app.config 字典可用于存储 Flask、扩展和应用自身的配置变量。

Flask-WTF 之所以要求应用配置一个密钥,是为了防止表单遭到跨站请求伪造(CSRF, cross-site request forgery)攻击。恶意网站把请求发送到被攻击者已登录的其他网站时,就 会引发 CSRF 攻击。Flask-WTF 为所有表单生成安全令牌,存储在用户会话中。令牌是一种加密签名,根据密钥生成。

使用Flask-WTF:

在服务器端,每个 Web 表单都由一个继承自 FlaskForm 的表示。这个类定义表单中的一组字段,每个字段都用对象表示。字段对象可附属一个或多个验证函数。验证函数用于验证用户提交的数据是否有效。例:

from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired

class NameForm(FlaskForm):
    name = StringField('What is your name?', validators=[DataRequired()])
    submit = SubmitField('Submit')

这个表单中的字段都定义为类变量,而各个类变量的值是相应字段类型的对象。在这个 示例中,NameForm 表单中有一个名为 name 的文本字段和一个名为 submit 的提交按钮。 StringField 类表示属性为 type="text" 的 HTML 元素。SubmitField 类表示属性 为 type="submit" 的 HTML 元素。字段构造函数的第一个参数是把表单渲染成 HTML 时使用的标注(label)。

结合:https://www.w3school.com.cn/tiy/t.asp?f=html_input_type_submit这里玩一下就知道了

StringField 构造函数中的可选参数 validators 指定一个由验证函数组成的列表,在接受用户提交的数据之前验证数据。验证函数 DataRequired() 确保提交的字段内容不为空。

PS: FlaskForm 基类由 Flask-WTF 扩展定义,所以要从 flask_wtf 中导入。然而,字段和验证函数却是直接从 WTForms 包中导入的。

在HTML中可以手工一个一个去渲染,实现:

但是更推荐用Bootstrap 预定义的表单样式渲染整个 Flask-WTF 表单:

{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}

完整例子:

具体效果可看4a分支

关于视图函数:

app.route 装饰器中多出的 methods 参数告诉 Flask,在 URL 映射中把这个视图函数注册为 GET 和 POST 请求的处理程序。如果没指定 methods 参数,则只把视图函数注册为 GET 请求的 处理程序。

这里有必要把 POST 加入方法列表,因为更常使用 POST 请求处理表单提交。表单也可以通过 GET 请求提交,但是 GET 请求没有主体,提交的数据以查询字符串的形式附加到 URL 中,在 浏览器的地址栏中可见。基于这个以及其他多个原因,处理表单提交几乎都使用 POST 请求。

提交表单后,如果数据能被所有验证函数接受,那么 validate_on_submit() 方法的返回值为 True,否则返回 False。这个函数的返回值决定是重新渲染表单还是处理表单提交的数据。

另外,试了下form.name.data = ''这句。如果不注释掉,点完submit后,输入框会被清空:

如果注释掉form.name.data = '' ,输入完毕后,框里面还保留着text:

如果用户提交表单之前没有输入名字,那么 DataRequired() 验证函数会捕获这个错误,如下图所示。注意这个扩展自动提供了多少功能。这说明,像 Flask-WTF 和 Flask-Bootstrap 这样设计良好的扩展能给应用提供十分强大的功能。

重定向和用户会话:

前一版 hello.py 存在一个可用性问题。用户输入名字后提交表单,然后点击浏览器的刷新 按钮,会看到一个莫名其妙的警告,要求在再次提交表单之前进行确认。之所以出现这种 情况,是因为刷新页面时浏览器会重新发送之前发送过的请求。如果前一个请求是包含表 单数据的 POST 请求,刷新页面后会再次提交表单。多数情况下,这并不是我们想执行的操 作,因此浏览器才要求用户确认。 很多用户不理解浏览器发出的这个警告。鉴于此,最好别让 Web 应用把 POST 请求作为浏 览器发送的最后一个请求。 这种需求的实现方式是,使用重定向作为 POST 请求的响应,而不是使用常规响应。重定向 是一种特殊的响应,响应内容包含的是 URL,而不是 HTML 代码的字符串。浏览器收到 这种响应时,会向重定向的 URL 发起 GET 请求,显示页面的内容。这个页面的加载可能 要多花几毫秒,因为要先把第二个请求发给服务器。除此之外,用户不会察觉到有什么不 同。现在,前一个请求是 GET 请求,所以刷新命令能像预期的那样正常运作了。这个技巧 称为 Post / 重定向 /Get 模式。 但这种方法又会引起另一个问题。应用处理 POST 请求时,可以通过 form.name.data 获取 用户输入的名字,然而一旦这个请求结束,数据也就不见了。因为这个 POST 请求使用重定向处理,所以应用需要保存输入的名字,这样重定向后的请求才能获得并使用这个名字, 从而构建真正的响应。 应用可以把数据存储在用户会话中,以便在请求之间“记住”数据。用户会话是一种私有 存储,每个连接到服务器的客户端都可访问。我们在前面介绍过用户会话,它是请求上下文中的变量,名为 session,像标准的 Python 字典一样操作。默认情况下,用户会话保存在客户端 cookie 中,使用前面设置的密钥加密签 名。如果篡改了 cookie 的内容,签名就会失效,会话也将随之失效。

发布了161 篇原创文章 · 获赞 71 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/yxpandjay/article/details/100007276