Flask表单验证

Posted Flask学习笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask表单验证相关的知识,希望对你有一定的参考价值。

wtf

WTForms

1.什么是WTForms

Web 网页一个重要的功能就是和客户端用户进行交互.

  • 在前端 html 提供了一个 form 标签,它是用于提供数据交互的接口. form 可以采用 GETPOST 方式以 Http请求消息的形式提交给后端服务器脚本(一般都是 POST).
  • 在后端服务器基本必须捕捉用于提交的 form 并做出验证判断.所以后端也相当于从新创建了表单.

WTForms 提供了一个框架,可以灵活的创建表单类,渲染和验证表单元素.

WTForms 把表单定义为一个类,在类中对formvalue 做验证.

官网

2.安装

$ conda install WTForms
# 或者
$ pip install WTForms

3.主要概念

  • Forms:是 WTForms 的核心类, FormsFields(约束域)的集合. Forms可以通过字典或属性的形式访问 Fields
    • Forms 提供了一个属性方法 validata(),用来表示整个表单时候验证成功
    • Forms提供了一个属性 errors 用来表示表单验证失败后的失败信息.
  • Fields:约束域,每一个 Fields 代表一个数据类型,类似与 ORM 的映射.它包含很多的数据类型,常用的有
    • IntegerFiled:整形约束,必须是整数.
    • DecimalField: decimal约束,必须使用 decimal.Decimal 类型的数据.
    • FloatFiled:浮点型约束
    • StringFiled:字符类型约束,基本大多数类型.
    • DateFiled:必须是 datetime.date 类型
    • DateTimeFiled:必须是 datetime.datetime 类型
    • TextField:表示 <input type='text'> 表单元素,可以使用 StringFIled
    • RaidoFIeld:表示 <input type='raido'> 的表单元素
    • BooleanField:表示 <input type='checkbox'> 的表单元素,可以指定 validators=[] ,也就是验证器为空,这样默认没有勾选为 False ,勾选为 True
    • SubmitField:表示 <input type='submit'> 的表单元素
    • PasswordField:表示 <input type='password'> 的表单元素,可以使用 StringFIled
    • FileField: 表示上传的文件
    • 以上 Fileds 约束域提供了一个属性 data ,可以获取表单的数据
  • 为了指定验证规则,每个 Fields 都有关键字参数 validators=[] 来指定验证的规则(它传入的是一个列表对象)
    • 常用的验证规则( from wtforms.validators import v_name),以下指定 v_name
    • Email:验证邮箱,使用了正则表达式
    • Equalto:比较两个字段的值
    • InputRequired:验证是否有数据
    • Length:长度限制,指定 min,max
    • NumberRange:验证数字是否在 min, max之间.
    • Ipaddress:验证是否为 ip地址,可以指定 ipv4/ipv6
    • Regexp:正则表达式验证
    • URL:验证URL
    • UUID:验证 UUID
    • 自定义验证:
class MyForm(Form):
    name = StringField('Name', [InputRequired()])
  # 必须定义函数名为 validate_变量名 变量名必须和上面的name相同,传递的参数必须是 filed
    def validate_name(self, field):
        if len(field.data) > 50:
            raise ValidationError('Name must be less than 50 characters')

4.构造项目

初始化一个项目,目录结构如下:

Form_demo
├── app.py            # 主app文件
├── blueprint_model         # 蓝图注册文件
│   ├── bpuser.py         # user 相关路由
│   └── __init__.py
├── config.py          # 配置文件
├── form_model.py       # 表单配置文件
├── static            # css,js 文件
└── templates          # 模板文件

实现最基本的HTML表单映射.

config.py

DEBUG = True
TEMPLATES_AUTO_RELOAD = True

bpuser.py

from flask import Blueprint
from flask import request,render_template
from form_model import Regist_Form

# 实例化
bp = Blueprint('user',__name__,url_prefix='/user/')

# 路由
@bp.route('/register/', methods=['GET', 'POST'])
def register():
    if request.method == 'GET':
        return render_template('register.html')
    else:
        form = Regist_Form(request.form)
       if form.validate():  # 返回True,False,如果验证成功返回True
            return render_template('register.html',error_info='Success')
        else:
            msg = ''
            for k,v in form.errors.items():
                msg = msg + '{}:{}'.format(k,v)
            print(msg)
            return render_template('register.html', error_info=msg)

app.py

from flask import Flask
import config
from blueprint_model import bpuser

app = Flask(__name__)
app.config.from_object(config)


@app.route('/')
def hello_world():
  return 'Hello World!'

# 注册蓝图
app.register_blueprint(bpuser.bp)


if __name__ == '__main__':
  app.run()

templates/register.html

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>注册页面</title>
</head>
<body>
 <form action="" method="post">
     <table>
         <tr>
             <td>用户名</td>
             <td><input type="text" name="username"></td>
         </tr>
         <tr>
             <td>密码</td>
             <td><input type="password" name="password"></td>
         </tr>
         <tr>
             <td>重复密码</td>
             <td><input type="password" name="repeat_password"></td>
         </tr>
         <tr>
             <td>邮箱</td>
             <td><input type="text" name="email"></td>
         </tr>
         <tr>
             <td>年龄</td>
             <td><input type="text" name="age"></td>
         </tr>
         <tr>
             <td>个人主页</td>
             <td><input type="text" name="blog"></td>
         </tr>
         <tr>
             <td>UUID</td>
             <td><input type="text" name="my_uuid" value="18e1fa3e-959f-4076-9e4f-6b258aa3a281"></td>
         </tr>
         <tr>
             <td>手机号码</td>
             <td><input type="text" name="phone"></td>
         </tr>
         <tr>
             <td>验证码</td>
             <td><input type="text" name="code"></td>
         </tr>
         <tr><td>
             <label for="#"><input type="submit"></label>
         </td></tr>

         {% if error_info %}
             <p>
             {{ error_info }}
             </p>
         {% endif %}
     </table>
 </form>
</body>
</html>

form_model.py

from wtforms import Form,StringField,PasswordField,IntegerField,ValidationError
from wtforms.validators import Length,EqualTo,Email,NumberRange,UUID,Regexp,URL


class Regist_Form(Form):
    """变量名必须和模板中的 from 中 input 标签的name保持一致"""
    # 名字必须大于3位小于10
    # message 指定返回的错误信息
    username = StringField(validators=[Length(min=3,max=10, message='用户名必须大于3')])
    # 密码必须大于6,小于12
    password = PasswordField(validators=[Length(min=6,max=12,message='密码必须长度大于6')])
    # 重复密码必须和 password字段一致
    repeat_password = PasswordField(validators=[EqualTo('password',message='和上次输入不符')])
    # 邮箱
    email = StringField(validators=[Email()])
    # 年龄
    age = IntegerField(validators=[NumberRange(18,100)])
    # 个人主页
    blog = StringField(validators=[URL()])
    # UUID
    my_uuid = StringField(validators=[UUID()])
    # 手机号码
    phone = StringField(validators=[Regexp(r'1[34578]\d{9}')])
    # 验证码, 要求必须是4位数,而且和服务器端匹配
    code = StringField(validators=[Length(min=4,max=4)])
    # 自定义验证
    def validate_code(self, filed):
        if filed.data != '1234':
            # 抛出 ValidationError
            raise ValidationError('验证码不符')

表单的验证需要注意的是validators=[] 传入的是一个列表.

- END -


以上是关于Flask表单验证的主要内容,如果未能解决你的问题,请参考以下文章

flask wtforms组件详解

表单类

Flask(表单验证 八)

flask处理表单数据

flask web 表单验证 WTForms

flask学习笔记(-Web 表单)