
3.1 使用Flask-WTF扩展

在Flask Web程序中,开发者可以使用Flask-WTF扩展快速开发出表单应用程序,例如快速实现常见的用户登录验证等功能。在本节的内容中,将详细讲解使用Flask-WTF扩展的知识。
3.1.1 Flask-WTF基础
通过使用Flask-WTF扩展,可以将WTForms(是一个支持多个Web框架的form组件,主要用于对用户请求数据进行验证)包进行包装,然后集成到Flask Web项目中。我们可以使用如下所示的pip命令安装Flask-WTF及其依赖。

Flask-WTF扩展具有很高的安全性,能够保护所有表单避免受到跨站请求伪造(Cross-Site Request Forgery,CSRF)攻击。Flask-WTF实现CSRF保护的原理如下。
1)在程序中使用Flask-WTF时首先需要设置一个密钥。
2)Flask-WTF使用密钥生成一个加密令牌。
3)使用生成的加密令牌验证请求中表单数据的真伪。
例如下面是一段设置Flask-WTF密钥的演示代码。

在Flask框架中,通常使用配置文件app.config来设置工程属性,这些属性通过字典的格式实现变量设置。在配置文件app.config中,使用标准的字典格式来设置SECRET_KEY密钥。这是一个通用密钥,可以在Flask工程和其他第三方扩展中使用。因为不同的程序需要使用不同的密钥,所以密钥的加密强度是不同的,这取决于变量值的保密程度。建议读者在文件app.config中设置SECRET_KEY密钥变量时,尽量使用比较生僻的字符串。
使用Flask-WTF时,可以用一个继承自Form的类来表示每个Web表单。在编写这个类的实现代码时,可以用类对象表示表单中的每一组字段。每个字段对象可对应一个或多个验证函数,通过验证函数可以验证用户在表单中提交的数据是否合法。
在Flask Web程序中,因为类FlaskForm由Flask-WTF扩展定义,所以可以从flask.wtf中导入FlaskForm。而字段和验证函数可以直接从WTForms包中导入,WTForms包可以支持如下所示的HTML标准字段。
• StringField:表示文本字段。
• TextAreaField:表示多行文本字段。
• PasswordField:表示密码文本字段。
• HiddenField:表示隐藏文本字段。
• DateField:表示日期的文本字段,值为datetime.date格式。
• DateTimeField:表示时间的文本字段,值为datetime.datetime格式。
• IntegerField:表示整数类型的文本字段值。
• DecimalField:表示Decimal类型的文本字段值。
• FloatField:表示浮点数类型的文本字段值为。
• BooleanField:表示复选框,取值只有两个:True和False。
• RadioField:表示单选框字段。
• SelectField:表示下拉列表字段。
• SelectMultipleField:表示下拉列表字段,可以同时选择多个值。
• FileField:表示文件上传字段,可以上传一个文件。
• SubmitField:表示提交表单按钮字段。
• FormField:表示把表单作为字段嵌入到另一个表单中。
• FieldList:表示一组指定类型的字段。
在WTForms中包含如下所示的内置验证函数。
• Email:验证电子邮件地址是否合法。
• EqualTo:比较两个字段的值是否相等,例如验证注册时两次输入的密码是否相等。
• IPAddress:验证是否是IPv4格式的IP地址。
• Length:验证输入字符串的长度是否合法。
• NumberRange:验证输入的值在某个范围内,例如要求用户名长度大于6小于12便是一个范围。
• Optional:无输入值时跳过其他验证函数。
• Required:用于确保在字段中有数据,可以保证输入值不为空。
• Regexp:使用正则表达式验证输入值。
• URL:验证URL地址是否合法。
• AnyOf:用于确保输入值在可选值列表中。
• NoneOf:用于确保输入值不在可选值列表中。
3.1.2 使用Flask-WTF处理表单
在下面的实例中,演示了使用Flask-WTF实现表单验证处理的过程。
源码路径:daima\3\3-1\biaodan01\
1)首先编写程序文件hello.py创建一个简单的Web表单,表单中包含一个StringField文本字段和一个SubmitField提交按钮。然后将所有表单中的字段定义为类变量,类变量的值和字段类型的对象相对应。文件hello.py的具体实现代码如下所示。

• 字段构造函数NameForm:在视图函数中创建一个NameForm类实例用于表示表单,设置表单中有两个元素,分别是一个名为name的文本字段和一个名为submit的提交按钮。类StringField表示这个表单的属性为type="text"的<input>类型元素,类SubmitField表示这个表单的属性为type="submit"的<input>类型元素。
• 视图函数index():渲染表单并接收表单中的数据。
• app.route:用于传递在修饰器中添加的methods参数,通过此参数告诉Flask在URL中把这个视图函数注册为GET和POST请求的处理程序。
注意:如果没设置methods参数,则只会把视图函数index()注册为GET请求的处理程序。建议读者把POST加入到methods列表中,因为使用POST请求方式处理提交表单数据的方法更加简洁。
• 验证函数validate_on_submit():提交表单后,如果数据通过验证函数的校验,那么函数validate_on_submit()的返回值为True,否则返回False。
2)在模板文件index.html中使用Flask-WTF和Flask-Bootstrap来渲染表单,具体实现代码如下所示。

上述代码的内容区现在有两部分,其中第一部分是页面头部,使用模板条件语句显示欢迎消息。Jinja2条件语句格式为{% if condition %}. . .{% else %}. . .{% endif %},会根据条件的计算结果显示相应的内容。
• 如果条件的计算结果为True,则会显示if和else指令之间的值。
• 如果条件的计算结果为False,则会显示else和endif指令之间的值。
在上述代码中,如果没有定义模板变量name,则会显示字符串“欢迎登录,出错了!”。内容区的第二部分使用函数wtf.quick_form()显示NameForm对象。
开始运行本项目,在命令行交互界面使用如下命令运行项目。

在浏览器中输入“http://127.0.0.1:5000/”后的执行效果如图3-1所示。在表单中随便输入一个用户名,例如输入“aaa”并单击“提交”按钮后,会在表单上面显示对用户“aaa”的欢迎信息,如图3-2所示。

图3-1 初始执行效果

图3-2 显示对用户“aaa”的欢迎信息
如果在表单为空时单击“提交”按钮,会显示“这是必填字段”的提示,如图3-3所示。

图3-3 表单为空时的提示