1.安装
pip3 install flask-wtf -i https://pypi,doban.com/simple
2.实例化
exts
from flask_wtf.csrf import CSRFProtect
csrf = CSRFProtect()
apps.py
from flask import Flask
from exts import csrf
from flask_wtf.csrf import CSRFProtect
def create_app():
app = Flask(__name__)
# 第一种绑定app
# csrf = CSRFProtect(app)
# 第二种绑定app
csrf.init_app(app)
# 必须需要设置SECRET_KEY这个配置项,form依赖session
app.config['SECRET_KEY'] = 'fgfhdf4564'
return app
3.使用
WTForms支持HTML字段:
WTForms支持HTML字段:
字段类型 | 说明 |
---|---|
StringField | 文本字段, 相当于type类型为text的input标签 |
TextAreaField | 多行文本字段 |
PasswordField | 密码文本字段 |
HiddenField | 隐藏文本字段 |
DateField | 文本字段, 值为datetime.date格式 |
DateTimeField | 文本字段, 值为datetime.datetime格式 |
IntegerField | 文本字段, 值为整数 |
DecimalField | 文本字段, 值为decimal.Decimal |
FloatField | 文本字段, 值为浮点数 |
BooleanField | 复选框, 值为True 和 False |
RadioField | 一组单选框 |
SelectField | 下拉列表 |
SelectMultipleField | 下拉列表, 可选择多个值 |
FileField | 文件上传字段 |
SubmitField | 表单提交按钮 |
FormFiled | 把表单作为字段嵌入另一个表单 |
FieldList | 子组指定类型的字段 |
Validators验证器
WTForms可以支持很多表单的验证函数:
验证函数 | 说明 |
---|---|
验证是电子邮件地址 | |
EqualTo | 比较两个字段的值; 常用于要求输入两次密钥进行确认的情况 |
IPAddress | 验证IPv4网络地址 |
Length | 验证输入字符串的长度 |
NumberRange | 验证输入的值在数字范围内 |
Optional | 无输入值时跳过其它验证函数 |
DataRequired | 确保字段中有数据 |
Regexp | 使用正则表达式验证输入值 |
URL | 验证url |
AnyOf | 确保输入值在可选值列表中 |
NoneOf | 确保输入值不在可选列表中 |
基础使用
form.py
from flask_wtf import FlaskForm
from wtforms import StringField, TextField, PasswordField
from wtforms.validators import DataRequired, ValidationError
class UserForm(FlaskForm):
name = StringField(label='name', validators=[DataRequired(message='用户名不能为空')])
password = PasswordField('name', validators=[DataRequired()])
def validate_name(self, name):
print('=============>', name.data)
if name.data == 'a':
raise ValidationError('不能是a')
view.py
@user_bp.route('/', methods=['get', 'post'])
def login():
form = UserForm()
if form.validate_on_submit():
# 验证通过会返回True
pass
# print('--------->', form.name.data)
return render_template('login.html', form=form)
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post">
{{form.csrf_token}}
{# label为表单类中定义此属性函数的第一个参数,如果需要添加样式,可以为字段指定id或class属性 #}
{{ form.name.label }}{{ form.name(id = 'username') }}<br>
{{ form.password.label }}{{ form.password }}<br>
<input type="submit">
</form>
</body>
</html>
文件上传
Flask-WTF 提供 FileField 来处理文件上传,它在表单提交后,自动从
flask.request.files
中抽取数据。FileField 的data
属性是一个 Werkzeug FileStorage 实例
form
from flask_wtf import FlaskForm
from flask_wtf.file import FileRequired, FileAllowed
from wtforms import StringField, TextField, PasswordField, FileField
from wtforms.validators import DataRequired, ValidationError
class PhotoForm(FlaskForm):
name = StringField(label='name', validators=[DataRequired(message='用户名不能为空')])
password = PasswordField('name', validators=[DataRequired()])
icon = FileField(label='用户头像', validators=[FileRequired(), FileAllowed(['jpg', 'png', 'gif'], message='必须是图片文件格式')])
def validate_name(self, name):
print('=============>', name.data)
if name.data == 'a':
raise ValidationError('不能是a')
view
from werkzeug import secure_filename
from flask_wtf.file import FileField
class PhotoForm(Form):
photo = FileField('Your photo')
@app.route('/upload/', methods=('GET', 'POST'))
def upload():
form = PhotoForm()
if form.validate_on_submit():
# 校验文件名称
filename = secure_filename(form.photo.data.filename)
form.photo.data.save('uploads/' + filename)
else:
filename = None
return render_template('upload.html', form=form, filename=filename)
html
<form action="/upload/" method="POST" enctype="multipart/form-data">
....
</form>
校验
自定义Validators验证器
第一种: in-line validator(内联验证器)
也就是自定义一个验证函数,在定义表单类的时候,在对应的字段中加入该函数进行认证。下面的my_length_check
函数就是用于判name
字段长度不能超过50.
def my_length_check(form, field):
if len(field.data) > 50:
raise ValidationError('Field must be less than 50 characters')
class MyForm(Form):
name = StringField('Name', [InputRequired(), my_length_check])
可重用的验证函数
一般是以
validate
开头,加上下划线再加上对应的field字段(validate_filed),浏览器在提交表单数据时,会自动识别对应字段所有的验证器,然后执行验证器进行判断。
class RegistrationForm(FlaskForm):
email = StringField('Email', validators=[DataRequired(), Length(1, 60), Email()])
username = StringField('Username', validators=[DataRequired(), Length(1, 60),
Regexp('^[A-Za-z][A-Za-z0-9_.]*$', 0, 'username must have only letters, numbers dots or underscores')])
password = PasswordField('Password', validators=[DataRequired(), EqualTo('password2', message='password must match')])
password2 = PasswordField('Confirm password', validators=[DataRequired()])
def validate_email(self, field):
if User.objects.filter(email=field.data).count() > 0:
raise ValidationError('Email already registered')
def validate_username(self, field):
if User.objects.filter(username=field.data).count() > 0:
raise ValidationError('Username has exist')
高级的validators
class Length(object):
def __init__(self, min=-1, max=-1, message=None):
self.min = min
self.max = max
if not message:
message = u'Field must be between %i and %i characters long.' % (min, max)
self.message = message
def __call__(self, form, field):
l = field.data and len(field.data) or 0
if l < self.min or self.max != -1 and l > self.max:
raise ValidationError(self.message)
length = Length
Widget组件
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask, render_template, request, redirect
from wtforms import Form
from wtforms import validators
from wtforms import widgets
class LoginForm(Form):
name = simple.StringField(
label='用户名',
validators=[
validators.DataRequired(message='用户名不能为空.'),
],
widget=widgets.TextInput(),
render_kw={'class': 'form-control'}
)
pwd = simple.PasswordField(
label='密码',
validators=[
validators.DataRequired(message='密码不能为空.'),
],
widget=widgets.PasswordInput(),
render_kw={'class': 'form-control'}
)
参考连接
Flask-WTF与WTForms的用法详解 - 简书 (jianshu.com)https://www.jianshu.com/p/7e16877757f8
flask入门到起飞(五) flask-wtf使用 - 简书 (jianshu.com)https://www.jianshu.com/p/3fd2a1f155f3