赵走x博客
网站访问量:151874
首页
书籍
软件
工具
古诗词
搜索
登录
Flask 实战:41、电子邮件进阶实践
Flask 实战:40、使用事务邮件服务SendGird
Flask 实战:39、使用Flask-Mail发送电子邮件
Flask 实战:38、数据库进阶实践
Flask 实战:37、更新数据库表
Flask 实战:36、定义关系
Flask 实战:35、在视图函数里操作数据库
Flask 实战:34、数据库操作:CRUD
Flask 实战:33、使用Flask-SQLAlchemy管理数据库
Flask 实战:32、ORM魔法
Flask 实战:31、数据库的分类
Flask 实战:30、单个页面多个表单
Flask 实战:29、单个表单多个提交按钮
Flask 实战:28、使用Flask-CKEditor集成富文本编辑器
Flask 实战:27、多文件上传
Flask 实战:26、文件上传
Flask 实战:25、自定义验证器
Flask 实战:24、使用宏渲染表单
Flask 实战:23、设置错误消息语言
Flask 实战:22、处理表单数据
Flask 实战:21、使用Flask-WTF处理表单
Flask 实战:20、HTML表单
Flask 实战:19、模板进阶实践
Flask 实战:18、模板结构组织
Flask 实战:17、模板辅助工具
Flask 实战:16、模板基本用法
Flask 实战:15、HTTP进阶实践
Flask 实战:14、Flask上下文
Flask 实战:13、HTTP响应
Flask 实战:12、HTTP请求
Flask 实战:11、请求响应循环
Flask 实战:10、Flask与MVC架构
Flask 实战:9、模板与静态文件
Flask 实战:8、Flask命令
Flask 实战:7、URL与端点
Flask 实战:6、项目配置
Flask 实战:5、Flask扩展
Flask 实战:4、Python Shell
Flask 实战:3、启动开发服务器
Flask 实战:2、Hello,Flask!
Flask 实战:1、初识Flask
Flask 实战:21、使用Flask-WTF处理表单
资源编号:75868
Python Web
Flask Web开发实战:入门、进阶与原理解析
热度:75
扩展Flask-WTF集成了WTForms,使用它可以在Flask中更方便地使用WTForms。Flask-WTF将表单数据解析、CSRF保护、文件上传等功能与Flask集成,另外还附加了reCAPTCHA支持。
扩展Flask-WTF集成了WTForms,使用它可以在Flask中更方便地使用WTForms。Flask-WTF将表单数据解析、CSRF保护、文件上传等功能与Flask集成,另外还附加了reCAPTCHA支持。 > 附注 reCAPTCHA([https://www.google.com/recaptcha/](https://www.google.com/recaptcha/) )是Google开发的免费验证码服务,在国内目前无法直接使用。 首先,和其他扩展一样,我们先用Pipenv安装Flask-WTF及其依赖: ``` $ pipenv install flask-wtf ``` Flask-WTF默认为每个表单启用CSRF保护,它会为我们自动生成和验证CSRF令牌。默认情况下,Flask-WTF使用程序密钥来对CSRF令牌进行签名,所以我们需要为程序设置密钥: ``` app.secret_key = 'secret string' ``` # 1、定义WTForms表单类 当使用WTForms创建表单时,表单由Python类表示,这个类继承从WTForms导入的Form基类。一个表单由若干个输入字段组成,这些字段分别用表单类的类属性来表示(字段即Field,你可以简单理解为表单内的输入框、按钮等部件)。下面定义了一个LoginForm类,最终会生成我们在前面定义的HTML表单: ``` from wtforms import Form, StringField, PasswordField, BooleanField, SubmitField from wtforms.validators import DataRequired, Length class LoginForm(Form): username=StringField('Username',validators=[DataRequired()]) password=PasswordField('Password',validators=[DataRequired(),Length(8,128)]) remember=BooleanField('Remember me') submit=SubmitField('Login') ``` 每个字段属性通过实例化WTForms提供的字段类表示。字段属性的名称将作为对应HTML`
`元素的name属性及id属性值。 >注意 字段属性名称大小写敏感,不能以下划线或validate开头。 这里的LoginForm表单类中定义了四个字段:文本字段StringField、密码字段Password-Field、勾选框字段BooleanField和提交按钮字段SubmitField。字段类从wtforms包导入,常用的WTForms字段如表4-1所示。  表4-1 常用的WTForms字段 有些字段最终生成的HTML代码相同,不过WTForms会在表单提交后根据表单类中字段的类型对数据进行处理,转换成对应的Python类型,以便在Python脚本中对数据进行处理。 通过实例化字段类时传入的参数,我们可以对字段进行设置,字段类构造方法接收的常用参数如表4-2所示。  表4-2 实例化字段类常用参数 在WTForms中,验证器(validator)是一系列用于验证字段数据的类,我们在实例化字段类时使用validators关键字来指定附加的验证器列表。验证器从wtforms.validators模块中导入,常用的验证器如表4-3所示。   表4-3 常用的WTForms验证器 在实例化验证类时,message参数用来传入自定义错误消息,如果没有设置则使用内置的英文错误消息,后面我们会了解如何使用内置的中文错误消息。 > 注意 validators参数接收一个传入可调用对象组成的列表。内置的验证器通过实现了__call__()方法的类表示,所以我们需要在验证器后添加括号。 在name和password字段里,我们都使用了DataRequired验证器,用来验证输入的数据是否有效。另外,password字段里还添加了一个Length验证器,用来验证输入的数据长度是否在给定的范围内。验证器的第一个参数一般为错误提示消息,我们可以使用message关键字传递参数,通过传入自定义错误信息来覆盖内置消息,比如: ``` name = StringField('Your Name', validators=[DataRequired(message=u'名字不能为空!')]) ``` 当使用Flask-WTF定义表单时,我们仍然使用WTForms提供的字段类和验证器,创建的方式也完全相同,只不过表单类要继承Flask-WTF提供的FlaskForm类。FlaskForm类继承自Form类,进行了一些设置,并附加了一些辅助方法,以便与Flask集成。因为本章的示例程序中包含多个表单类,为了便于组织,我们创建了一个forms.py脚本,用来存储所有的表单类: ``` from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, BooleanField, SubmitField from wtforms.validators import DataRequired, Length class LoginForm(FlaskForm): username=StringField('Username',validators=[DataRequired()]) password=PasswordField("Password",validators=[DataRequired(),Length(8,128)]) remember=BooleanField('Remember me') submit=SubmitField('Login') ``` 配置键WTF_CSRF_ENABLED用来设置是否开启CSRF保护,默认为True。Flask-WTF会自动在实例化表单类时添加一个包含CSRF令牌值的隐藏字段,字段名为csrf_token。 # 2、输出HTML代码 以我们使用WTForms创建的LoginForm为例,实例化表单类,然后将实例属性转换成字符串或直接调用就可以获取表单字段对应的HTML代码: ``` >>> form = LoginForm() >>> form.username() u'
' >>> form.submit() u'
' ``` 字段的
元素的HTML代码则可以通过“form.字段名.label”的形式获取: ``` >>> form.username.label() u'
Username
' >>> form.submit.label() u'
Submit
' ``` 在创建HTML表单时,我们经常会需要使用HTML`
`元素的其他属性来对字段进行设置。比如,添加class属性设置对应的CSS类为字段添加样式;添加placeholder属性设置占位文本。默认情况下,WTForms输出的字段HTML代码只会包含id和name属性,属性值均为表单类中对应的字段属性名称。如果要添加额外的属性,通常有两种方法。 ### 1.使用render_kw属性 比如下面为username字段使用render_kw设置了placeholder HTML属性: ``` username = StringField('Username', render_kw={'placeholder': 'Your Username'}) ``` 这个字段被调用后输出的HTML代码如下所示: ```
``` ### 2.在调用字段时传入 在调用字段属性时,通过添加括号使用关键字参数的形式也可以传入字段额外的HTML属性: ``` >>> form.username(style='width: 200px;', class_='bar') u'
' ``` class是Python的保留关键字,在这里我们使用class_来代替class,渲染后的`
`会获得正确的class属性,在模板中调用时则可以直接使用class。 > 注意 通过上面的方法也可以修改id和name属性,但表单被提交后,WTForms需要通过name属性来获取对应的数据,所以不能修改name属性值。 # 3、在模板中渲染表单 为了能够在模板中渲染表单,我们需要把表单类实例传入模板。首先在视图函数里实例化表单类LoginForm,然后在render_template()函数中使用关键字参数form将表单实例传入模板,如代码所示: ``` from forms import LoginForm @app.route('/basic') def basic(): form = LoginForm() return render_template('basic.html', form=form) ``` 在模板中,只需要调用表单类的属性即可获取字段对应的HTML代码,如果需要传入参数,也可以添加括号,basic.html代码清单: ```
{{ form.csrf_token }} {{ form.username.label }}{{ form.username }}
{{ form.password.label }}{{ form.password }}
{{ form.remember }}{{ form.remember.label }}
{{ form.submit }}
``` 需要注意的是,在上面的代码中,除了渲染各个字段的标签和字段本身,我们还调用了form.csrf_token属性渲染Flask-WTF为表单类自动创建的CSRF令牌字段。form.csrf_token字段包含了自动生成的CSRF令牌值,在提交表单后会自动被验证,为了确保表单通过验证,我们必须在表单中手动渲染这个字段。 >提示 Flask-WTF为表单类实例提供了一个form.hidden_tag()方法,这个方法会依次渲染表单中所有的隐藏字段。因为csrf_token字段也是隐藏字段,所以当这个方法被调用时也会渲染csrf_token字段。 渲染后获得的实际HTML代码如下所示: ```
Username
Password
Remember me
``` 如果你运行了示例程序,访问[http://localhost:5000/basic](http://localhost:5000/basic) 可以看到渲染后的表单,页面中的表单和我们在上面使用HTML编写的表单完全相同。 在前面我们介绍过,使用render_kw字典或是在调用字段时传入参数来定义字段的额外HTML属性,通过这种方式添加CSS类,我们可以编写一个Bootstrap风格的表单,如bootstrap.html代码所示: ``` ...
{{ form.csrf_token }}
{{ form.username.label }} {{ form.username(class='form-control') }}
{{ form.password.label }} {{ form.password(class='form-control') }}
{{ form.remember(class='form-check-input') }} {{ form.remember.label }}
{{ form.submit(class='btn btn-primary') }}
... ``` 为了使用Bootstrap,我们在模板中加载了Bootstrap资源。如果你运行了示例程序,可以访问[http://localhost:5000/bootstrap](http://localhost:5000/bootstrap) 查看渲染后的实际效果,如图4-2所示。  图4-2 Bootstrap风格表单 如果你想手动编写HTML表单的代码,要注意表单字段的name属性值必须和表单类的字段名称相同,这样在提交表单时WTForms才能正确地获取数据并进行验证,具体会在后面介绍。