flask 使用Flask-WTF处理表单 --
使用Flask-WTF处理表单
扩展Flask-WTF继承了WTFforms,使用它可以在flask中更方便的使用WTForms。Flask-WTF将表单数据解析、CSRF保护、文件上传等功能与Flask集成。
先用pipenv安装flask-wtf及其依赖:
激活pipenv环境
看下环境中安装了什么
pipenv install flask-wtf,安装flask-wtf
装完了后:
flask-wtf默认为每个表单启用CSRF保护,它为我们自动生成和验证CSRF令牌。默认情况下,fflask-wtf使用程序秘钥来对CSRF令牌进行签名(token),所以我们需要为程序设置秘钥:
app.secret_key = ‘secret string’
定义WTForms表单来
使用WTForms创建表单时,表单由python类表示,这个类继承从STForms导入的Form类。一个表单由若干个输入字段组成,这些字段分别用表单类的类属性来表示(字段即field,可以简单理解为表单内的输入框、按钮等部件),下面定义了一个LoginForm类,最终会生成像之前定义的HTML表单:
from wtforms import Form, StringField, PasswordField, BooleanField, SubmitField from wfforms.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('Log in')
每个字段属性通过实例化WTForms提供的字段类来表示。字段属性的名称将作为对应HTML<input>元素的name属性及id属性值。
字段属性名称大小写敏感,不能以下划线或validate开头。
这里的LoginForm表单类中定义了四个字段:文本字段StringField、密码字段Pawword-Field、勾选框字段BooleanField和提交按钮字段SubmitField。字段类从wtforms包导入,有些字段最终生成的HTML代码相同,不过WTForms会在表单提交后根据表单类中字段的类型对数据进行处理,转换成对应的python类型,以便在python脚本中对数据进行处理。
常用的WTForms字段如下表:
通过实例化字段类时传入的参数,我们可以对字段进行设置,字段类构造方法接受的常用参数如下表:
在WTForms中,验证器(validator)是一系列用于验证字段数据的类,我们在实例化字段类时使用validators关键字来指定附加的验证器列表。验证器从wtforms.validators模块中导入,常用的验证器,如下表:
在实例化验证类时,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文件(form/forms.py),用来存储各种表单类。
下面例子是继承FlaskForm类的LoginForm表单:
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('Log in')
配置键WTF_CSRF_ENABLED用来设置是否开启CSRF保护,默认为True。Flask-WTF会自动在实例化表单时添加一个包含CSRF令牌值的隐藏字段,字段名为csrf_token。
输出HTML代码
以我们使用WTForms创建的LoginForm为例,实例化表单类,然后将实例属性转换成字符串或直接调用就可以获取表单字段对应的HTML代码(需要在虚拟环境激活上下文):
>>> form = LoginForm()
>>> form.username()
u'<input id="username" name="username" required type="text" value="">'
>>> form.submit()
u'<input id="submit" name="submit" type="submit" value="Log in">'
>>> form.password()
u'<input id="password" name="password" required type="password" value="">'
>>> form.remember()
u'<input id="remember" name="remember" type="checkbox" value="y">'
字段的<label>元素的HTML代码则可以通过”form.字段名.label”的形式获取:
>>> form.username.label()
u'<label for="username">Username</label>'
>>> form.submit.label()
u'<label for="submit">Log in</label>'
在虚拟环境下,需要激活程序上下文(app_context)和请求上下文(request_context),才能实例化运行上面的程序,激活上下文可以通过以下方式:
1、 pipenv shell 激活虚拟环境
2、到appForm.py所在目录:D:\flask\FLASK_PRACTICE
3、运行python进入python命令行模式
4、激活程序上下文:
>>> from appForm import app
>>> from flask import current_app
>>> app_ctx=app.app_context()
>>> app_ctx.push()
>>> current_app.name
'appForm'
5、激活请求上下文:
>>> from appForm import app
>>> from flask import request
>>> app_re=app.test_request_context('/html')
>>> app_re.push()
>>> request.method
'GET'
6、把LoginForm()类定义运行一下
>>> 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('Log in')
之后就可以实例化这个类,做其他的事情了
添加额外的属性
在创建HTML表单时,我们经常会需要使用HTML<input>元素的其他属性来对字段进行设置。比如class属性设置对应的CSS类为字段添加样式;添加placeholder属性设置占位文本。默认情况下WForms输出的字段HTML代码只会包含id和name属性,属性值均为表单类中对应的字段属性名称。如果要添加额外的属性,通常有两种方法。
使用render_kw属性
比如下面为username字段使用render_kw设置了placeholder HTML属性:
username = StringField(‘Username’ render_kw={‘placeholder’: ‘Your Username’})
这个字段被调用后输出的HTML代码是:
<input type=”text” id=”username” name=”username” placeholder=”Your Username”>
调用字段时传入
在调用字段属性时,通过添加括号使用关键字参数的形式也可以传入字段额外的HTML属性:
>>> form.username()
u'<input id="username" name="username" required type="text" value="">'
>>> form.username(style='width:200px;',class_='bar')
u'<input class="bar" id="username" name="username" required style="width:200px;" type="text" value="">'
class是pyhton的保留字,我们使用class_来代替class,渲染后的<input>会获得正确的classl属性,在模板中调用时则可以直接使用class。
通过上面的方法也可以修改id和name属性,但表单被提交后,WTForms需要通过name属性来获取对应的数据,所以不能修改name属性值。