Form表单,在Web应用中无处不在。比如: 用户登录表单, 用户注册表单。
如果有个框架,能把这些共性抽象出来,那就能大量简化我们的工作。Python的 WTForms 就提供了这些功能,这里我们就要结合Flask的 WTForms 扩展—— Flask-WTF ,来介绍如何在Web应用中制作表单。
pip install -i https://pypi.douban.com/simple Flask-WTF
直接继承这个表单类
WTForms 让我们在后端代码中定义表单类,并列出表单的字段和相应的验证规则。
现在让我们先定义一个 MyForm 类:
from flask_wtf import FlaskForm
from jsonschema import ValidationError
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Length, Email, EqualTo
class LoginForm(FlaskForm):
email=StringField(label='电子邮箱',
validators=[
DataRequired(message='邮箱不能为空'),
Length(1,15,message='长度不符合条件'),
Email(message='请输入有效的邮箱地址,比如:[email protected]')
])
password=PasswordField('密码',
validators=[
DataRequired(message='密码不能为空')
])
submit=SubmitField(u'登录')
__all__ = (
'BooleanField', 'DecimalField', 'DateField', 'DateTimeField', 'FieldList',
'FloatField', 'FormField', 'IntegerField', 'RadioField', 'SelectField',
'SelectMultipleField', 'StringField', 'TimeField',
)
def __init__(self, label=None, validators=None, filters=tuple(),
description='', id=None, default=None, widget=None,
render_kw=None, _form=None, _name=None, _prefix='',
_translations=None, _meta=None):
__all__ = (
'DataRequired', 'data_required', 'Email', 'email', 'EqualTo', 'equal_to',
'IPAddress', 'ip_address', 'InputRequired', 'input_required', 'Length',
'length', 'NumberRange', 'number_range', 'Optional', 'optional',
'Required', 'required', 'Regexp', 'regexp', 'URL', 'url', 'AnyOf',
'any_of', 'NoneOf', 'none_of', 'MacAddress', 'mac_address', 'UUID',
'ValidationError', 'StopValidation'
)
表单域类型 | 描述 |
---|---|
StringField | 文本框 |
TextAreaField | 多行文本框 |
PasswordField | 密码输入框 |
HiddenField | 隐藏文本框 |
DateField | 接收给定格式datetime.date型的文本框 |
DateTimeField | 接收给定格式datetime.datetime的文本框 |
IntegerField | 接收整型的文本框 |
DecimalField | 接收decimal.Decimal型的文本框 |
FloadField | 接收浮点型的文本框 |
BooleanField | 带有True和False的复选框 |
RadioField | 一组单选框 |
SelectField | 下拉选择框 |
SelectMutipleField | 下拉多选框 |
FileField | 文件上传框 |
SubmitField | 表单提交按钮 |
FormField | 将一个表单作为表单域嵌入到容器表单中 |
FieldList | 给定类型的表单域列表 |
然后在主函数中实例化表单对象,并对表单信息进行验证:
@app.route('/login/',methods=['POST','GET'])
def login():
# 1.实例化表单对象
form=LoginForm()
# 1)是否为post提交表单信息
# 2)是否通过验证函数
if form.validate_on_submit():
# 获取表单内容
email=form.email.data
password=form.password.data
if email=='[email protected]' and password=='anan':
flash('登录成功')
return '登录成功'
else:
return '登录失败'
else:
return render_template('bs_login.html',form=form)
if __name__=='__main__':
app.run()
点击了表单上的提交按钮时,form.validate_on_submit() 判断会做下面两件事情:
验证通过后,获取表单数据有两种方法:
form.字段名.data
form.data['字段名']
验证规则 | 说明 |
---|---|
DataRequired | 验证必填项 |
验证邮件地址格式 | |
EqualTo | 验证必须同另一个字段值相同,它需传入另一个字段的名称‘fieldname’ |
Length | 验证输入字符串长度,它有两个参数:‘min’最小长度,‘max’最大长度,缺省的话不检查 |
NumberRange | 验证输入数值的范围,它有两个参数:‘min’最小值,‘max’最大值,缺省的话不检查 |
URL | 验证URL格式 |
IPAddress | 验证IP地址格式,默认IPV4,你可以传入“ipv6=True”来验证IPV6地址 |
MacAddress | 验证Mac地址格式 |
Any0f | 传入一个列表作为参数,验证是否匹配列表中的任一值 |
None0f | 传入一个列表作为参数,验证是否与列表中的所有值都不同 |
Regexp | 正则表达式验证,需传入一个正则表达式,它还有一个flags参数,如果你传入“re.IGNORECASE”,则会忽略大小写 |
因为flash内容存储在session会话中,session会话存储是加密的,因此需要设置密钥。
"""
File:config.py
Author: anning
Date:-03-20
Connect:[email protected]
Description:
配置信息
"""
SECRET_KEY='anan'
在主函数中通过form_pyfile将配置文件传入:
app.config.from_pyfile('config.py')
login.html
<!DOCTYPE HTML >
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
{% for message in get_flashed_messages() %}
<p style="color: red">{{message}}</p>
{% endfor %}
<form action="/login/" method="post">
{{form.hidden_tag()}}
{{form.email.label}} {{form.email}} {{form.email.errors}}
{{form.password.label}} {{form.password}} {{form.password.errors}}
{{form.submit()}}
</form>
</body>
</html>
你可以在表单类创建自定义的验证函数,一个简单的例子:
def validate_username(self, field):
# field.data是用户输入的数据。
if field.data == 'admin':
# ValidationError从wtforms导入,用来向用户显示错误信息,
# 验证函数的名称由validate_fieldname组成。
raise ValidationError(u'超级管理员已被注册,换一个吧。')
也可以在这里对用户数据进行预处理:
# 这个函数对用户输入的网址进行处理(字段名为website)。
def validate_website(self, field):
if field.data[:4] != "http":
field.data = "http://" + field.data
表单文件forms.py中添加内容:
class RegisterForm(FlaskForm):
# StringField
# PasswordField
name = StringField(
label="用户名",
# 验证: 用户名不能为空的
validators=[DataRequired(message='用户名不能为空'),Length(5, 12, message="用户名长度必须在5-12之间") ]
)
password = PasswordField(
label="密码",
validators=[
DataRequired(),
# 验证密码长度是否为6~8之间, 如果不是, 则报错;
Length(6, 16, message="密码格式不正确"),
]
)
repassword = PasswordField(
"确认密码",
validators=[
DataRequired(),
# 验证当前表单输入的内容和password这个表单输入的内容是否一致, 如果不一致, 报错;
EqualTo('password', message="密码不一致")
]
)
submit = SubmitField(label="注册")
视图函数文件app.py中添加内容:
from flask_bootstrap import Bootstrap
@app.route('/register/',methods=['POST','GET'])
def register():
form=RegisterForm()
if form.validate_on_submit():
return '获取性别%s'%(form.gender.data)
else:
return render_template('register.html',form=form)
前端文件register.html:
<!--导入Bootstrap的基模板,自动加载css样式和js函数-->
{% extends 'bootstrap/base.html' %}
<!--导入html代码并且起别名-->
{% import 'bootstrap/wtf.html' as wtf %}
{% block title %}
注册
{% endblock %}
{% block content %}
<div style="width: 70%;margin: 0 auto">
<h1>用户注册</h1>
<hr>
{{wtf.quick_form(form)}}
</div>
{% endblock %}