一、 WTForms引入
Form表单,在Web应用中无处不在。比如: 用户登录表单, 用户注册表单。
- 所有的表单项都有共性,比如有文字输入框,单选框,密码输入框等;
- 表单的验证也有共性,比如有非空验证,长度限制,类型验证等。
如果有个框架,能把这些共性抽象出来,那就能大量简化我们的工作。Python的 WTForms 就提供了这些功能,这里我们就要结合Flask的 WTForms 扩展, Flask-WTF ,来介绍如何在Web应用中制作表单。
二、安装
pip install -i https://pypi.douban.com/simple Flaks-WTF
直接继承这个表单类
三、定义表单文件
WTForms 让我们在后端代码中定义表单类,用的时候直接继承,我们只需要列出表单的字段和相应的验证规则。现在让我们先定义一个 MyForm 类:
1、常见表单域字段类型
2、常见验证规则
3、简单实例
表单文件:forms.py
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Length, Email
class LoginForm(FlaskForm):
# validators:验证
email = StringField(label='电子邮箱',
validators=[DataRequired(message='邮箱不能为空'),
Length(1, 15, message='长度不符合条件'),
Email(message='请输入有效的邮箱地址')])
password = PasswordField(label='密码',
validators=[DataRequired(message='密码不能为空'),
Length(1, 8, message='长度不符合条件')])
submit = SubmitField(label='登录')
查看StringField源代码,需要填入这些参数:
label为字段名
vaildators为验证规则
查看vaildators源代码,可以有这些规则:
app.py文件
from flask import Flask, render_template
from flask表单处理.forms import LoginForm
app = Flask(__name__)
app.config.from_pyfile('config.py')
@app.route('/login/', methods=['GET', 'POST'])
def login():
# 实例化表单对象
form = LoginForm()
# 1)是否为post提交表单信息 2)是否通过了验证
if form.validate_on_submit():
# 获取表单的内容
email = form.email.data
password = form.password.data
if email == '123.qq.com' and password == '123':
return '登录成功'
else:
return '登录失败'
else:
return render_template('login.html', form=form)
if __name__ == '__main__':
app.run()
点击了表单上的提交按钮时, form.validate_on_submit() 判断会做下面两件事情:
- 通过 is_submitted() 通过判断HTTP方法来确认是否提交了表单
- 通过 WTForms 提供的 validate() 来验证表单数据
当validate()验证未通过时,会在表单字段下面显示我们传进去的错误提示(例如message= ‘邮箱不能为空’)。
验证通过后,获取表单数据有两种方法:
form.字段名.data
form.data['字段名']
配置文件 config.py
""" 配置信息 """
SECRET_KEY = 'hello'
前端页面 login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login/" method="post">
{{ form.hidden_tag() }}
{{ form.email.label }} {{ form.email() }} {{ form.email.errors }}<br/>
{{ form.password.label }} {{ form.password() }} {{ form.password.errors }}<br/>
{{ form.submit() }}
</form>
</body>
</html>
form.hidden_tag() 会生成一个隐藏的标签,其中会渲染任何隐藏的字段,最主要的是 CSRF 字段。
CSRF (Cross-Site Request Forgery跨站请求伪造)是一种通过伪装来自受信任用户的请求,来发送恶意攻击的方法, WTForms 默认开启CSRF 保护。
运行结果:
4、用户注册与Bootstrap结合
forms.py文件中添加:
# 注册
class RegisterForm(FlaskForm):
name = StringField(label='用户名',
validators=[DataRequired(message='用户名不能为空')])
password = PasswordField(label='密码',
validators=[DataRequired(),
Length(6, 16, message='密码格式不正确')])
repassword = PasswordField(label='确认密码',
validators=[DataRequired(),
EqualTo('password', message='密码不一致')]) #EqualTo 和哪个字段填的内容一样
email = StringField(label='邮箱',
validators=[DataRequired(),
Email(message='邮箱格式错误')])
phone = StringField(label='电话号码',
validators=[DataRequired(),
#验证电话号码,首位为1,11位,使用正则表达式 \d{10}表示数值出现10次
Regexp(r'1\d{10}', message='电话号码格式错误')])
# 单选框:SelectField
gender = SelectField( label='性别',
coerce=int, # 填写的信息传入后台的类型
choices=[(1, '男'),(2,'女')] # 下拉列表的选项
)
# 下拉多选框:SelectMultipleField
tech = SelectMultipleField(label='擅长领域',
coerce=int,
choices=[(1,'python'),(2,'linux'),(3,'java'),(4,'c++')])
submit = SubmitField(label='注册')
app.py文件中添加:
from flask_bootstrap import Bootstrap
@app.route('/register/', methods=['GET', 'POST'])
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: 40%; margin: 0 auto">
<h1>用户注册</h1><hr/>
{{ wtf.quick_form(form)}}
{% endblock %}
运行结果:
5、自定义验证
(1)进行判断,抛出异常
# 自定义验证
# 定义函数名称的时候:validate_字段名 name 是字段名,验证时会来找这个函数
def validate_name(self, field): # field:前端对象
# field.data :用户输入的数据
if field.data == 'admin':
# ValidationError,像用户显示错误信息
raise ValidationError('超级管理员已被注册')
(2)对数据进行预处理
#对用户输入的网址进行处理,字段名是 website
def validate_website(self, field):
if field.data[:4] != 'http':
field.data = 'http://' + field.data