当前位置: 首页 > 工具软件 > WTForms > 使用案例 >

WTForms表单验证

西门安歌
2023-12-01

1.0 Flask-WTF

flask-wtf 是简化了Flask-WTForms的第三方库,wtfroms表单验证的两个主要功能是,验证用户数据提交的合法性和渲染模板,也包括一些其他的功能,如CSRF保护,文件上传等。安装flask-wtf默认也会安装WTForms.

pip install flask-wtf

2.0 表单验证

2.1 如下:有一个.py的文件,在里面创建一个RegistForm的注册验证表单。

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

#各类表单验证
class RegistForm(Form):
    username = StringField(validators=[length(min=3, max=10, message='用户名长度不正确')])
    password = StringField(validators=[length(min=3, max=10, message='密码长度不正确')])
    password_verify = StringField(validators=[EqualTo('password', message='两次密码长度不相等')])

上面的例子,指定了username 的长度,password密码长度,输入的密码需要和password_verify相等才能通过验证。

2.2 Email表单验证模块

#email表单验证
class LoginForm(Form):
    # email = StringField(validators=[Email(message='格式不正确')])
    #NumberRange表单
    # age = IntegerField(validators=[NumberRange(1, 80)])
    #InputRequired表单
    # username = StringField(validators=[InputRequired()])
    #做个手机验证
    # telphone = StringField(validators=[Regexp(r'1[3589]\d{9}')])
    # 正则表达式,第一个为1,第二个为(3589)任意,后面九个任意。
    #URL表单
    # info = StringField(validators=[URL()])
    #验证码表单
    captche = StringField(validators=[Length(min=4,max=4)])
    #想验证验证码必须使用下面的方法validate_captche,加下划线+需要验证的数据,进行验证,否则失败
    def validate_captche(self, field):
        if field.data != '5678':
            raise ValidationError('验证码错误') #ValidationError 可允许传出的错误

完成表单后就需要导入html文件了

2.3 web页面显示模块index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">

<!--    <table>-->
<!--        <tr>-->
<!--            <td>邮箱:</td>-->
<!--            <td><input type="text" name="email"></td>-->
<!--        </tr>-->

<!--        <tr>-->
<!--            <td><input type="submit" value="提交"></td>-->

<!--        </tr>-->
<!--    </table>-->
<!--    <table>-->
<!--        <tr>-->
<!--            <td>年龄:</td>-->
<!--            <td><input type="text" name="age"></td>-->
<!--        </tr>-->

<!--        <tr>-->
<!--            <td><input type="submit" value="提交"></td>-->

<!--        </tr>-->

<!--    </table>-->

<!--    <table>-->

<!--        <tr>-->
<!--            <td>用户名:</td>-->
<!--            <td><input type="text" name="username"></td>-->
<!--        </tr>-->

<!--        <tr>-->
<!--            <td><input type="submit" value="提交"></td>-->

<!--        </tr>-->

<!--    </table>-->

<!--    <table>-->

<!--        <tr>-->
<!--            <td>手机号:</td>-->
<!--            <td><input type="text" name="telphone"></td>-->
<!--        </tr>-->

<!--        <tr>-->
<!--            <td><input type="submit" value="提交"></td>-->

<!--        </tr>-->

<!--    </table>-->

<!--<table>-->

<!--    <tr>-->
<!--        <td>个人中心:</td>-->
<!--         <td><input type="text" name="info"></td>-->
<!--    </tr>-->
<!--    <tr>-->
<!--         <td><input type="submit" value="提交"></td>-->

<!--    </tr>-->

<!--</table>-->

    <table>

    <tr>
        <td>验证码:</td>
         <td><input type="text" name="captche"></td>
    </tr>
    <tr>
         <td><input type="submit" value="提交"></td>

    </tr>

</table>


</body>
</html>

主文件代码

from flask import Flask,request,render_template
from forms import RegistFrom,LoginForm


app = Flask(__name__)

# @app.route('/',methods=("GET","POST"))
# def login():
#     if request.method == "GET":
#         return render_template('index.html')
#     else:
#         form = RegistFrom(request.form)
#         if form.validate():
#             return '登录成功'
#         else:
#             print(form.errors)
#             return '登录失败'

@app.route('/login/',methods=["GET","POST"])
def login():
    if request.method == "GET":
        return render_template('index.html')
    else:
        form = LoginForm(request.form)
        if form.validate():
            return '登录成功'
        else:
            print(form.errors)
            return '登录失败'

if __name__ == '__main__':
    app.run(debug=True,port=8384)

3.0 渲染模板

form 还可以渲染模板,少写一点点代码,如下重写例子:

####例子:
class RegistForm(Form):
    username = StringField(validators=[length(min=3, max=10, message='用户名长度不正确')])
    password = StringField(validators=[length(min=3, max=10, message='密码长度不正确')])
    password_verify = StringField(validators=[EqualTo('password', message='两次密码长度不相等')])

========================================================================
### 重写例子:
@app.route('/login/',methods=["GET","POST"])
def login():
	form = RegistForm(request.form)
	if request == "POST" and form.validate():
		user = User(username = form.username.date,password = form.password.date)
		db.session.add(user)
		db.session.commit()
		return "注册成功"
	return render_template('index.html',form = form)

以上不同的地方在于渲染模板的时候添加了参数form,这样在模板中就可以使用表单form变量

4.0 文件上传

  1. 在模板,form表单中,需要指定encotype=‘mutipart/form-data’,才能上传文件
  2. 在后台如果想获取上传的文件就应该用request.files.get(‘avatar’)来获取
  3. 保存文件前先使用werkzeug.utils.secure_filename来对上传的文件进行过滤,这样才能保证不会有安全问题
  4. 获取上传来的文件后,使用avatar.save(路径)方法来保存文件
  5. 从服务器上读取文件,应该定义一个url与视图函数来获取指定的文件,在这个视图函数中使用send_form_directory(文件的目录,文件名)来获取

如下:

==============主文件===============
from flask import Flask, request, render_template
import os
from werkzeug.utils import secure_filename
from werkzeug.datastructures import CombinedMultiDict
from forms import UploadForm

app = Flask(__name__)

# @app.route('/')
# def index():
#     return 'aaa'

@app.route('/upload/',methods=('GET','POST'))
def upload1():
    if request.method == 'GET':
        return render_template('upload.html')
    else:
        # desc = request.form.get('desc')
        # image_file = request.files.get('image_file')
        # #判断名称,不支持中文格式,如上传文件包含中文,会自动去除
        # filename = secure_filename(image_file.filename)
        # image_file.save(os.path.join('images', filename))
        # return "文件保存成功"
        form = UploadForm(CombinedMultiDict([request.form, request.files])) #进行合并,在传给表单验证
        print(form)
        if form.validate():
            desc = request.form.get('desc')
            image_file = request.files.get('image_file')
            filename = secure_filename(image_file.filename)
            image_file.save(os.path.join('images', filename))
            return "文件保存成功"
        else:
            print(form.errors)
            return '文件上传失败'

=====从服务器上读取文件,建立一个视图函数
@app.route('/images/<filename>/')
def get_image(filename)
	return send_form_directory(路径,文件名)

模板文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--#文件上传表单必须添加enctype="multipart/form-data" 这个属性-->
    <form action="" method="post" enctype="multipart/form-data">

        <table>
            <tr>
                <td>头像</td>
                <td><input type="file" name="image_file"></td>
            </tr>

            <tr>
                <td>描述</td>
                <td><input type="text" name="desc"></td>
            </tr>

            <tr>
                <td><input type="submit" value='上传'></td>
            </tr>
        </table>

    </form>
</body>
</html>

4.1 对上传文件使用表单验证forms.py

#设置表单验证
from wtforms import Form, FileField, StringField
from wtforms.validators import Regexp, InputRequired
from flask_wtf.file import FileAllowed, FileRequired

class UploadForm():
    # 对上传的文件进行验证
    image_file = FileField(validators=[FileRequired(), FileAllowed(['jpg', 'png'])])
    desc = StringField(validators=[InputRequired()])
 类似资料: