Flask表单验证功能的完成

385 阅读3分钟

Flask表单验证

  1. 表单设计

创建form标签,设置action为url_for('register'),method为POST。表示将register视图函数反转为URL,在之后单击‘提交’按钮时,会把所有form标签下输入框中的内容都提交给这个URL,并且会以POST方式提交。在form标签下,最后添加了一个type为‘submit’的input标签,被渲染出来是一个按钮。

  1. 表单类编写

注册页面表单设计好后,需要对字段有一定要求,比如用户名长度、邮箱格式、密码是否一致...因此这里通过抓包形式获取注册时的请求数据。在forms.py文件下进行表单类编写。

from wtforms import Form, StringField, ValidationError
from wtforms.validators import length, email, equal_to
class RegisterForm(Form):
    username = StringField(validators=[length(min=3, max=20, message='请输入正确长度的用户名!')])
    email = StringField(validators=[email(message='请输入正确格式的邮箱!')])
    password = StringField(validators=[length(min=6, max=20, message='请输入正确长度的密码!')])
    confirm_password = StringField(validators=[equal_to('password', message='两次密码不一致!')])

从wtforms中导入Form基类,所有表单类都必须继承自Form基类,字段名称必须和相对应的HTML文件中表单元素的name一致。因为当前这4个字段属性都是字符串类型,所以用StringField,其他还有IntegerField等等。validators为验证器集合,可以存放多个验证器,不满足要求会提示错误信息,错误信息即为message中内容。

  1. 视图函数中使用表单
@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():
            email = form.email.data
            username = form.username.data
            password = form.password.data

            print('email:', email)
            print('username:', username)
            print('password:', password)
            return '注册成功!'
        else:
            for errors in form.errors.values():
                for error in errors:
                    flash(error)
            return redirect(url_for('register'))

首先用RegisterForm类创建一个form对象,request.form是一个类字典类型,保存了从浏览器中提交上来的表单数据,调用form.validate()方法判断RegisterForm中定义的所有字段是否验证通过,全部通过验证则通过 form.<字段名>.data 获取对应字段数据(这里不从request.form获取数据,因为reques.form是服务器获取到的从浏览器提交的数据,都是字符串类型,而通过form对象获取到的数据会经过处理,保留数据类型)。

获取到所有数据后,就可以把数据存储到数据库中或进行其他操作。

若验证失败,通过form.errors.values()获取所有错误内容即之前的message信息,并存储到flash中,form.errors是字典类型,加了values后是列表。在模板中把flash消息显示出来。

<ul>
{% for message in get_flashed_messages() %}
<li>{{ message }}</li>
{% endfor %}
</ul>

使用flash消息,需先配置SECRET_KEY,密钥内容可以随意字符

app.config['SECRET_KEY'] = 'AASDAD'

redirect为重定向函数,输入一个URL后,自动跳转到另一个URL所在的地址

  1. 自定义验证字段

自定义验证逻辑,比如已经注册过的邮箱不能再次注册,这时需要查询数据,判断邮箱是否存在。自定义某个字段的验证逻辑可以通过在表单类中自定义方法 validate_<字段名> 来实现。

class RegisterForm(Form):
    username = StringField(validators=[length(min=3, max=20, message='请输入正确长度的用户名!')])
    email = StringField(validators=[email(message='请输入正确格式的邮箱!')])
    password = StringField(validators=[length(min=6, max=20, message='请输入正确长度的密码!')])
    confirm_password = StringField(validators=[equal_to('password', message='两次密码不一致!')])

    def validate_email(self, field):
        email = field.data
        if email in register_email:
            raise ValidationError('邮箱已经被注册!')
        return True

register_email变量可在之前进行定义,表示数据库中已经被注册的邮箱。之后在视图函数中调用form.validate()方法时,RegisterForm底层会自动调用validate_email方法,并传递一个field参数,验证的是哪个字段,field就代表相应字段。通过field.data拿到对应值。若验证失败,抛出wtforms.ValidationError异常,并指定一个错误消息,该错误消息会出现在form.errors中。