这个插件库主要有两个作用。
第一个是做表单验证,将用户提交上来的数据进行验证是否符合系统要求。
第二个是做模版渲染。 (了解即可)
官网:https://wtforms.readthedocs.io/en/latest/index.html
Flask-WTF是简化了WTForms操作的一个第三方库。WTForms表单的两个主要功能是验证用户提交数据的合法性以及渲染模板。而Flask-WTF还包括一些其他的功能:CSRF保护,文件上传等。
安装Flask-WTF默认也会安装WTForms,因此使用以下命令来安装Flask-WTF和WTForms:
pip install flask-wtf
示例代码:
main.py
from flask import Flask, render_template, request
from wtforms import Form, StringField
from wtforms.validators import Length, EqualTo
app = Flask(__name__)
@app.route('/')
def index():
return 'hello world'
class RegisterForm(Form):
uname = StringField(validators=[Length(min=2, max=10, message='用户名长度2-10之间')])
pwd = StringField(validators=[Length(min=2, max=10)])
pwd2 = StringField(validators=[Length(min=2, max=10), EqualTo('pwd', message='2次密码不一致')])
@app.route('/register/', methods=['GET', 'POST'])
def register():
if request.method == 'GET':
return render_template('register.html')
else:
form = RegisterForm(request.form)
if form.validate(): # 验证成功:True, 失败:False
return '验证成功'
else:
return f'验证失败!{form.errors}'
if __name__ == '__main__':
app.run(debug=True)
register.html
注册
运行结果:
页面把数据提交上来,需要经过表单验证,进而需要借助验证器来进行验证,以下是常用的内置验证器。
字符串长度限制,有min和max两个值进行限制,message用于提示信息。
username = StringField(validators=[Length(min=3,max=10,message="用户名长度必须在3到10位之间")])
验证数据是否和另外一个字段相等,常用的就是密码和确认密码两个字段是否相等。
password_repeat = StringField(validators=[Length(min=6,max=10),EqualTo("password")])
验证上传的数据是否为邮箱数据格式 如:[email protected]。
email = StringField(validators=[Email()])
验证该项数据为必填项,即要求该项非空。
username = StringField(validators=[input_required()])
数值的区间,有min和max两个值限制,如果处在这两个数字之间则满足。
age = IntegerField(validators=[NumberRange(12,18)])
定义正则表达式进行验证,如验证手机号码。
phone = StringField(validators=[Regexp(r'1[34578]\d{9}')])
必须是URL的形式 如http://www.baicu.com。
home_page = StringField(validators=[URL()])
验证数据是UUID类型。
uuid = StringField(validators=[UUID()])
示例代码:
main.py
from flask import Flask, render_template, request
from formcheck import RegisterForm
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello! '
@app.route('/register/', methods=['GET', 'POST'])
def register():
if request.method == 'GET':
return render_template('register.html')
else:
form = RegisterForm(request.form)
if form.validate():
return '验证成功!'
else:
return f'验证失败!{form.errors}'
if __name__ == '__main__':
app.run(debug=True)
formcheck.py
from wtforms import Form, StringField, IntegerField
from wtforms.validators import Email, InputRequired, NumberRange, Regexp, URL, UUID
class RegisterForm(Form):
# pip install wtforms[email]
email = StringField(validators=[Email()])
uname = StringField(validators=[InputRequired()])
age = IntegerField(validators=[NumberRange(min=18, max=50)])
phone = StringField(validators=[Regexp('^1[3456789]\d{9}$')])
homepage = StringField(validators=[URL()])
uuid = StringField(validators=[UUID()])
register.html
注册页面
运行结果:
只有当WTForms内置的验证器不够使的时候,才需要使用自定义验证器。
如果想要对表单中的某个字段进行更细化的验证,那么可以针对这个字段进行单独的验证。
自定义验证器步骤如下:
示例代码:
main.py
from flask import Flask, render_template, request, session
from formcheck import LoginForm
from random import randint
import os
app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(32)
@app.route('/')
def index():
return 'Hello! '
@app.route('/login/', methods=['GET', 'POST'])
def register():
if request.method == 'GET':
code = randint(1000, 9999)
session['code'] = code
return render_template('login.html', code=code)
else:
form = LoginForm(request.form)
if form.validate():
return '验证成功!'
else:
return f'验证失败!{form.errors}'
if __name__ == '__main__':
app.run(debug=True)
formcheck.py
from wtforms import Form, StringField
from wtforms.validators import Length, ValidationError
from flask import session
class LoginForm(Form):
code = StringField(validators=[Length(4, 4)]) # 不能满足数据内容的匹配
def validate_code(self, field):
font_code = field.data
server_code = str(session.get('code'))
print(f'前端的数据是:{font_code} ==== 服务器端的数据是:{server_code}')
print(f'前端的数据是:{type(font_code)} ==== 服务器端的数据是:{type(server_code)}')
if font_code != server_code:
raise ValidationError('验证码错误')
login.html
注册页面
运行结果:
渲染模版是WTForms的第二个作用。
示例代码:
main.py
from flask import Flask, render_template, request
from formcheck import LoginForm
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello! '
@app.route('/login/', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
form = LoginForm()
return render_template('login.html', form=form)
else:
return '登录成功'
if __name__ == '__main__':
app.run(debug=True)
formcheck.py
from wtforms import Form, StringField, IntegerField, BooleanField, SelectField
from wtforms.validators import Length, InputRequired, NumberRange
class LoginForm(Form):
uname = StringField(validators=[Length(min=2, max=10)])
# uname = StringField('用户名:',validators=[Length(min=1,max=10)])
age = IntegerField('年龄:', validators=[InputRequired(), NumberRange(min=15, max=25)])
remember = BooleanField('记住我:')
address = SelectField('地址:', choices=[('bj', '北京'), ('sh', '上海'), ('gz', '广州')])
login.html
Document
运行结果:
问题遗留:
上面代码执行中,WTforms渲染模板验证没有生效!
关键点:
示例代码:
main.py
from flask import Flask, render_template, request
from werkzeug.datastructures import CombinedMultiDict
from werkzeug.utils import secure_filename
import os
from formcheck import UpLoadForm
app = Flask(__name__)
UPLOAD_PATH = os.path.join(os.path.dirname(__file__), 'images')
@app.route('/upload/', methods=['GET', 'POST'])
def upload():
if request.method == 'GET':
return render_template('upload.html')
else:
form = UpLoadForm(CombinedMultiDict([request.form, request.files]))
if form.validate():
img_file = form.pic.data
file_name = secure_filename(img_file.filename)
img_file.save(os.path.join(UPLOAD_PATH, file_name))
return '上传文件成功!'
else:
return f'{form.errors}'
if __name__ == '__main__':
app.run(debug=True)
formcheck.py
from wtforms import Form, FileField
from flask_wtf.file import FileAllowed, FileRequired
class UpLoadForm(Form):
pic = FileField(validators=[FileRequired(), FileAllowed(['jpg', 'png', 'gif'])])
upload.py
Document
运行结果: