目录
模板是让信息从服务器流向用户,但网络上的页面不都仅仅是一个展示的功能,往往伴随着和用户的交互,服务器需要根据用户提交的信息进行处理后返回给用户特定的信息,这个时候就需要用到表单功能。
传统的表单Form通过POST请求提交之后,可以通过request.form对象访问用户提交的数据,假如有很多表单的操作,这样的方式会进行繁琐且重复的操作。Flask-WTF扩展就可以很好的解决这个问题,使得处理表单变得简单。直接pip install flask-wtf安装。
Flask-WTF无需在应用层初始化,但要求配置一个密匙,用来为表单生成安全令牌防止CSRF(跨站请求伪造)攻击,详细的可参考CSRF
配置代码如下:
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'
先上代码:
from flask_wtf import FlaskForm # 表单的基类
from wtforms import StringField, SubmitField # 表单组件
from wtforms.validators import DataRequired # 数据验证函数
class NameForm(FlaskForm): # 所有的表单类都继承与FlaskForm
# StringField 表示 type="text"的html <input>元素,name表示元素的id="name", validators表示数据需要经过那些验证,所以是一个列表
name = StringField('What is your name?', validators=[DataRequired()])
# 表示<input id="submit", type="submit"/>
submit = SubmitField()
解释释加载了代码上,基本上和直接看代码理解的一样,相当于用Python写了个前端的表单。字段和验证函数是从wtforms包导入的:
支持的HTML标准字段如下:
字段类型 | 说明 |
---|---|
BooleanField | 复选框,值为True/False |
DateField | 文本字段,值为datatime.date格式 |
DateTimeField | 文本字段,值为datatime.datetime格式 |
DecimalField | 文本字段,值为decimal.Decimal格式 |
FileField | 文件上传字段 |
HiddenField | 隐藏的文本字段 |
MultipleFileField | 多文件上传字段 |
FieldList | 一组指定类型的字段 |
FloatField | 文本字段,值为浮点数 |
FormField | 把一个表单作为字段嵌入另一个表单 |
IntegerField | 文本字段 |
PasswordField | 密码文本字段 |
RadioField | 一组单选按钮 |
SelectField | 下拉列表 |
SelectMultipleField | 下拉列表,可选多个值 |
SubmitField | 表单提交按钮 |
StringField | 文本字段 |
TextAreaField | 多行文本字段 |
支持的验证函数如下:
验证函数 | 说明 |
---|---|
DataRequired | 确保转换类型后有数据 |
验证电子邮件地址 | |
EqualTo | 比较两个字段的值,常用于输入两次密码校验 |
InputRequired | 确保转换类型前有数据 |
IPAddress | 验证IPv4地址 |
Length | 验证输入字符串的长度 |
MacAddress | 验证MAC地址 |
NumberRange | 验证输入的值在数字范围内 |
Optional | 允许字段中没输入,将跳过其它验证函数 |
Regexp | 使用正则验证输入值 |
URL | 验证URL |
UUID | 验证UUID |
AnyOf | 确保输入的值在一组可能的值中 |
NoneOf | 确保输入的值不再一组可能的值中 |
假设视图函数处理后传递给模板一个表单form,模板可以按照以下方式渲染表单:
<form method="POST">
{{ form.hidden_tag() }} <!-- 隐藏字段,供CSRF防护机制使用 -->
{{ form.name.label }} {{ form.name(id='my-text-field')}} <!-- 可以在字段内定义属性 -->
{{ form.submit() }}
</form>
这样的方式显得繁琐且丑陋,可以使用bootstrap组件进行渲染,方式如下:
{% import "bootstrap/wtf.html" as wtf %} <!-- 类似于python的import -->
{{ wtf.quick_form(form) }}
视图函数在表单处理时有两个任务,一个是渲染表单,一个是接收表单提交的数据,方式如下:
@app.route('/', methods=['GET', 'POST']) # 需要支持POST请求
def index():
name = None
form = NameForm()
if form.validate_on_submit(): # 验证表单是否提交且数据经过验证
name = form.name.data
form.name.data = ''
return render_template('index.html', form=form, name=name) # 初始化时和表单提交时,返回的方式统一处理
这其中有一个点,提交的时候数据怎么是到form对象里的呢?这是组件已经封装好了的,具体的有知道的小伙伴可以告诉我,十分感谢。因为模板、表单,在实际开发中我们并用不到,处理的基本都是JSON数据,所以这一部分写的也不是很详细,了解就好。
参考资料:《Flask Web开发(第二版)》