1、flask-WTF简介

Flask-WTF是简化了WTForms操作的一个第三方库。WTForms表单的两个主要功能是验证用户提交数据的合法性以及渲染模板。当然还包括一些其他的功能:CSRF保护,文件上传等。安装Flask-WTF默认也会安装WTForms。
pip install flask-wtf —user

2、表单验证

1、在主入口文件中写入”简单的表单验证”

templates文件夹中的view1.html文件

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Verification</title>
  6. </head>
  7. <body>
  8. {% macro input(name, value="", type="text") %}
  9. <input name="{{ name }}", value="{{ value }}", type="{{ type }}">
  10. {% endmacro %}
  11. <form action="" method="post">
  12. <!-- 表单提交到flask中 -->
  13. 用户名:{{ input("username") }}<br>
  14. 密码:{{ input("password") }}<br>
  15. 确认密码:{{ input("password_repate") }}<br>
  16. {{ input(value="注册", type="submit") }}
  17. </form>
  18. </body>
  19. </html>

主入口文件:

  1. from flask import Flask, request, render_template
  2. app = Flask(__name__)
  3. app.config["TEMPLATES_AUTO_RELOAD"] = True
  4. @app.route('/')
  5. def home():
  6. return "首页"
  7. @app.route('/cation/', methods=["GET", "POST"])
  8. def verification():
  9. if request.method == "GET":
  10. return render_template("view1.html")
  11. else:
  12. username = request.form.get("username")
  13. password = request.form.get("password")
  14. password_repate = request.form.get("password_repate")
  15. if len(username) < 3 or len(username) > 10:
  16. return "用户名长度非法"
  17. if len(password) < 3 or len(password) > 10:
  18. return "密码长度非法"
  19. if password != password_repate:
  20. return "密码和确认密码不一致"
  21. if __name__ == '__main__':
  22. app.run(debug=True)

这样的写法与业务逻辑无关,并且显得代码非常冗余,这里只需要返回判断的结果即可,所以下面使用flask-wtf进行操作

2、通过wtforms进行表单验证

templates文件夹中的view1.html文件,不进行改变
新建forms.py文件

  1. from wtforms import Form, StringField, validators
  2. from wtforms.validators import Length, Regexp, EqualTo
  3. # 表单验证,继承Form类
  4. class RegistForm(Form):
  5. # if len(username) < 3 or len(username) > 10:
  6. # return "用户名长度非法"
  7. username = StringField(validators=[Length(min=3, max=10)])
  8. # if len(password) < 3 or len(password) > 10:
  9. # return "密码长度非法"
  10. password = StringField(validators=[Length(min=3, max=10)])
  11. # if password != password_repate:
  12. # return "密码和确认密码不一致"
  13. password_repate = StringField(validators=[Length(min=3, max=10), EqualTo("password")])

代码注解:

  1. from wtforms import Form, StringField, validators
  2. # Form类用于继承
  3. # StringField表示字段,用于接收
  4. # validators验证器用来写各种验证种类
  5. from wtforms.validators import Length, Regexp, EqualTo
  6. # 导入验证的种类

注意点:

  1. username = StringField(validators=[Length(min=3, max=10)])
  1. 用户名:{{ input(name="username") }}<br>

注意名称的一致性!!!
验证的种类有:

  1. __all__ = (
  2. 'DataRequired', 'data_required', 'Email', 'email', 'EqualTo', 'equal_to',
  3. 'IPAddress', 'ip_address', 'InputRequired', 'input_required', 'Length',
  4. 'length', 'NumberRange', 'number_range', 'Optional', 'optional',
  5. 'Required', 'required', 'Regexp', 'regexp', 'URL', 'url', 'AnyOf',
  6. 'any_of', 'NoneOf', 'none_of', 'MacAddress', 'mac_address', 'UUID',
  7. 'ValidationError', 'StopValidation'
  8. )

主入口文件

  1. from flask import Flask, request, render_template
  2. # 从定义的forms.py文件中导入RegistForm
  3. from forms import RegistForm
  4. app = Flask(__name__)
  5. app.config["TEMPLATES_AUTO_RELOAD"] = True
  6. @app.route('/')
  7. def home():
  8. return "首页"
  9. @app.route('/cation/', methods=["GET", "POST"])
  10. def verification():
  11. # 判断:如果是是GET请求
  12. if request.method == "GET":
  13. return render_template("view1.html")
  14. else:
  15. form = RegistForm(request.form)
  16. # form.validate()判断是否通过表单请求
  17. if form.validate():
  18. return "验证通过"
  19. else:
  20. # 返回验证的错误信息
  21. print(form.errors)
  22. return "验证失败"
  23. if __name__ == '__main__':
  24. app.run(debug=True)

在网页中输入输入:
image.png
返回值:
image.png
image.png
返回值是英文值,如何修改返回值,通过修改验证中的message参数

  1. class RegistForm(Form):
  2. username = StringField(validators=[Length(min=3, max=10, message="非法的用户名长度")])
  3. password = StringField(validators=[Length(min=3, max=10, message="非法的密码长度")])
  4. password_repate = StringField(validators=[Length(min=3, max=10), EqualTo("password", message="两次输入不一致")])

返回值:
image.png
此时只要将返回结果渲染到前端,就能够返回中文结果了

3、常用的验证器

支持自己写(正则),都有message参数,可以叠加(如有特殊需求,可以修改原码)

  1. # EqualTo 判断两者是否相等
  2. password_confirm = StringField(validators=[EqualTo("想要相等的变量名或者值")])
  3. # Length 限制长度
  4. username = StringField(validators=[Length(min=3, max=10)])
  5. # Email 判断是否为邮箱格式
  6. # 需要安装额外支持pip install email-validator --user
  7. email = StringField(validators=[Email()])
  8. # NumberRange 给定一个数值范围
  9. # 使用的不是StringField而是IntegerField或者其他数字的字段
  10. age = IntegerField(validators=[NumberRange(1,120))
  11. # InputRequired 字段必须要填写
  12. name = StringField(validators=[InputRequired()])
  13. # Regexp 写正则表达式
  14. # 输入手机号
  15. phone_number = StringField(validators=[Regexp(r"1[358]/d{9}")])
  16. # URL 判断网址格式
  17. url = StringField(validators=[URL()])

小例子:验证码(可以自己定义方法,但是要注意命名)

  1. class CaptchaForm(Form):
  2. # 验证码
  3. captcha = StringField(validators=[Length(min=4, max=4, message="请检查输入长度")])
  4. # 这里的写法要注意必须是validate_ + 需要验证的字段
  5. print(type(captcha))
  6. # 写法必须是validate_ + 需要验证的字段
  7. def validate_captcha(self, field):
  8. # 这里把验证码写死
  9. # print(field.data)
  10. # <class 'wtforms.fields.core.UnboundField'> , 为什么是field, 原因大概在这
  11. # 通过field.data可以获取出对应的值
  12. if field.data != "1234":
  13. # 主动抛出异常
  14. raise ValidationError("验证失败")

3、知识点-form模板渲染

form可以渲染模板,减少一定的代码量,下面对forms.py文件进行改写

  1. class RegistForm(Form):
  2. username = StringField("用户名", validators=[Length(min=3, max=10)])
  3. password = StringField("密码", validators=[Length(min=3, max=10)])
  4. password_repate = StringField("确认密码", validators=[Length(min=3, max=10), EqualTo("password")])

增加一个位置参数,用来在html文件中,做标签起到提示作用
将主入口文件进行相应的修改

  1. @app.route('/cation/', methods=["GET", "POST"])
  2. def verification():
  3. # 判断:如果是是GET请求
  4. if request.method == "GET":
  5. return render_template("view1.html")
  6. else:
  7. form = RegistForm(request.form)
  8. # form.validate()判断是否通过表单请求
  9. if form.validate():
  10. # 保存数据至数据库中
  11. user = User(name=form.username.data, password=form.password.data)
  12. db.session.add(user)
  13. db.session.commit()
  14. # 打印相关的信息
  15. print(form.username.label)
  16. print(form.username())
  17. # 渲染到前端, 并传入表单数据
  18. return render_template("view1.html", form=form)
  19. else:
  20. # 返回验证的错误信息
  21. print(form.errors)
  22. return "验证失败"

image.png
通过传入form变量,在模板中可以使用表单form变量了 return render_template(“view1.html”, form=form)
增加新的模板文件(由于定义了宏,所以下面就只能开新得模板了,流下能力不够的泪水)

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Verification</title>
  6. </head>
  7. <body>
  8. <form action="" method="post">
  9. <table>
  10. <tr>
  11. <td>{{ form.username.label }}</td>
  12. <td>{{ form.username() }}</td>
  13. </tr>
  14. <tr>
  15. <td>{{ form.password.label }}</td>
  16. <td>{{ form.password() }}</td>
  17. </tr>
  18. <tr>
  19. <td></td>
  20. <td><input type="submit" value="提交"></td>
  21. </tr>
  22. </table>
  23. </form>
  24. </body>
  25. </html>