flask(十五)----表单验证(后端)

任何从客户端发送来的数据,后端都是不信任的。 

 

表单传送过程:客户端--->flask(request)--->取出

注册表单

<!--{{url_for()}}代表form表单将要发送到后端的路由-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>
<body>
    <!--{{url_for()}}代表form表单将要发送到后端的路由-->
    <form action="{{url_for('register')}}" method="post">
        <label>用户名:</label><input name="name" type="text">
        <br>
        <label>手机号:</label><input name="phone" type="text">
        <br>
        <label>密码:</label><input name="pwd" type="password">
        <br>
        <label>确认密码:</label><input name="confirm_pwd" type="password">
        <br>
        <br>
        <input type="submit" value="立即注册">
        <br>
    </form>

</body>
</html>

后端校验方式(1):

import re

from flask import Flask, request, render_template, Response
from werkzeug.exceptions import abort

app = Flask(__name__)

@app.route('/register',methods=["GET","POST"])
def register():
    if request.method == 'GET':
        return render_template('register.html')
    name = request.form.get('name')
    phone = request.form.get('phone')
    pwd = request.form.get('pwd')
    pwd_confirm = request.form.get('confirm_pwd')
    # 表单验证
    if not name:
        res = Response(render_template('register.html', msg='用户名不能为空'), status='412', content_type='text/html;charset=utf-8')
        abort(res)
    if not re.match(r'^1[3,4,5,6,7,8,9]\d{9}$', phone):
        res = Response(render_template('register.html', msg='手机号码格式错误'), status='412', content_type='text/html;charset=utf-8')
        abort(res)
    if len(pwd)<6:
        res = Response(render_template('register.html', msg='密码必须大于6位'), status='412', content_type='text/html;charset=utf-8')
        abort(res)
    if pwd_confirm != pwd:
        res = Response(render_template('register.html', msg='密码不一致'), status='412',content_type='text/html;charset=utf-8')
        abort(res)
    return Response(render_template('login.html', msg='注册成功'), status='200',content_type='text/html;charset=utf-8')

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

后端校验方式(2):

import re

from flask import Flask, request, render_template, Response
from werkzeug.exceptions import abort

app = Flask(__name__)

def form_check(form):
    name = form.get('name')
    phone = form.get('phone')
    pwd = form.get('pwd')
    pwd_confirm = form.get('confirm_pwd')
    # 表单验证
    if not name:
        res = Response(render_template('register.html', msg='用户名不能为空'), status='412',
                       content_type='text/html;charset=utf-8')
        abort(res)
    if not re.match(r'^1[3,4,5,6,7,8,9]\d{9}$', phone):
        res = Response(render_template('register.html', msg='手机号码格式错误'), status='412',
                       content_type='text/html;charset=utf-8')
        abort(res)
    if len(pwd) < 6:
        res = Response(render_template('register.html', msg='密码必须大于6位'), status='412',
                       content_type='text/html;charset=utf-8')
        abort(res)
    if pwd_confirm != pwd:
        res = Response(render_template('register.html', msg='密码不一致'), status='412',
                       content_type='text/html;charset=utf-8')
        abort(res)


@app.route('/register',methods=["GET","POST"])
def register():
    if request.method == 'GET':
        return render_template('register.html')
    form = request.form
    form_check(form)
    return Response(render_template('login.html', msg='注册成功'), status='200', content_type='text/html;charset=utf-8')

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

后端校验方式(3):

import re

from flask import Flask, request, render_template, Response
from werkzeug.exceptions import abort

app = Flask(__name__)

@app.route('/register',methods=["GET","POST"])
def register():
    if request.method == 'GET':
        return render_template('register.html')
    name = request.form.get('name')
    phone = request.form.get('phone')
    pwd = request.form.get('pwd')
    pwd_confirm = request.form.get('confirm_pwd')
    # 表单验证
    if not name:
        return render_template('register.html', msg='用户名不能为空'),412, {"content_type":'text/html;charset=utf-8'}

    if not re.match(r'^1[3,4,5,6,7,8,9]\d{9}$', phone):
        return render_template('register.html', msg='手机号码格式错误'), 412, {"content_type": 'text/html;charset=utf-8'}

    if len(pwd)<6:
        return render_template('register.html', msg='密码应大于6位'), 412, {"content_type": 'text/html;charset=utf-8'}

    if pwd_confirm != pwd:
        return render_template('register.html', msg='密码不一致'), 412, {"content_type": 'text/html;charset=utf-8'}

    return Response(render_template('login.html', msg='注册成功'), status='200',content_type='text/html;charset=utf-8')

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

效果

后端验证方式(4):

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField
from wtforms.validators import Regexp, DataRequired, Length, EqualTo


class RegisterForm(FlaskForm):  # 继承自FlaskForm
    """
    表单属性要和前端传递过来的表单name属性一致,最好也要和数据库里面的字段一致
    """
    name = StringField(label='用户名',
                       validators=[Length(3, 12, message='用户名格式错误'),
                                   DataRequired('用户名不能为空')])
    phone = StringField(label='手机号码',
                        validators=[Regexp(r'^1[3,4,5,6,7,8,9]\d{9}$', message='手机号码格式错误'),
                                    DataRequired('手机号码不能为空')])
    pwd = PasswordField(label='密码',
                        validators=[Length(6, 18, message='密码格式错误'),
                                    DataRequired('密码不能为空')])
    confire_pwd = PasswordField('确认密码', validators=[EqualTo("pwd", message='确认密码格式错误')])
import os
from src.form_check.helpers.forms import RegisterForm

from flask import Flask, request, render_template, Response

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24)  # 随机生产字符串,flask需要传给前端,不然报错


@app.route('/')
def hello():
    return 'hello world'


@app.route('/register', methods=["GET", "POST"])
def register():
    form = RegisterForm(formdata=request.form)  # RegisterForm需要一个form表单的参数。
    # form = RegisterForm(data=request.json)  # 如果form表单数据是通过ajax请求或者postman之类工具发送过来的json格式数据,通过data=request.json来接收。

    if request.method == 'GET':
        return render_template('register.html', form=form)  # 此处将通过form=form,将csrf_token数据传回前端
    # 如果是post,开始验证
    # form.validate():验证主函数
    # form.data:获取所有数据
    # form.errors:获取错误信息
    if form.validate():
        return 'success'
    return f'error:{form.errors}'


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

后端必须要返回一个SECRET_KYEY给前端(csrf_token密钥),不然报错。 

form = RegisterForm(data=request.json)  # 如果form表单数据是通过ajax请求或者postman之类工具发送过来的json格式数据,通过data=request.json来接收,不可再用formdata=request.json接收。 

前端:添加form.hidden_tag()后,前端的cookies里就会多一个crsf_token数据,保证安全。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>
<body>
    <form action="{{url_for('register')}}" method="post">
        <!--添加form.hidden_tag()后,前端的cookies里就会多一个crsf_token数据,保证安全-->
        {{ form.hidden_tag() }}
        <label>用户名:</label><input name="name" type="text">
        <br>
        <label>手机号:</label><input name="phone" type="text">
        <br>
        <label>密码:</label><input name="pwd" type="password">
        <br>
        <label>确认密码:</label><input name="confirm_pwd" type="password">
        <br>
        <br>
        <input type="submit" value="立即注册">
        {{msg}}
        <br>
    </form>

</body>
</html>

效果:

FlaskForm中其他可校验字段类型:

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, IntegerField, DecimalField, DateField, RadioField, SelectField, \
    SelectMultipleField, TextAreaField, BooleanField, SubmitField
from wtforms.validators import Regexp, DataRequired, Length, EqualTo, Email, NumberRange


class RegisterForm(FlaskForm):  # 继承自FlaskForm
    """
    表单属性要和前端传递过来的表单name属性一致,最好也要和数据库里面的字段一致
    """
    name = StringField(label='用户名',
                       validators=[Length(3, 12, message='用户名格式错误'),
                                   DataRequired('用户名不能为空')])
    phone = StringField(label='手机号码',
                        validators=[Regexp(r'^1[3,4,5,6,7,8,9]\d{9}$', message='手机号码格式错误'),
                                    DataRequired('手机号码不能为空')])
    pwd = PasswordField(label='密码',
                        validators=[Length(6, 18, message='密码格式错误'),
                                    DataRequired('密码不能为空')])
    confire_pwd = PasswordField('确认密码', validators=[EqualTo("pwd", message='确认密码格式错误')])
    # Text Field类型,文本输入框,Email格式
    email = StringField('email address', validators=[Email()])
    # IntegerField类型,必须输入整数数值,范围16~70
    age = IntegerField('age', validators=[NumberRange(min=16, max=70)])
    # DecimalField类型,必须输入数值,显示时保留1位小数
    height = DecimalField('height(Centimeter)', places=1)
    # DateField类型,必须输入'年-月-日'格式日期
    birthday = DateField('birthday', format='%Y-%m-%d')
    # RadioField类型,单选框,choices里面的内容会在ul标签里,里面每1项(值,显示名)是一对
    gender = RadioField('gender', choices=[('m', 'Male'), ('f', 'Female')], validators=[DataRequired()])
    # SelectField类型,下拉单选框,choices里面内容会在option里,里面每1项(值,显示名)是一对
    job = SelectField('job', choices=[('teacher', 'Teacher'), ('doctor', 'Doctor'), ('engineer', 'Engineer')])
    # SelectMultipleField类型,下拉多选框,choices里面内容会在option里,里面每1项(值,显示名)是一对
    hobby = SelectMultipleField('hobby', choices=[('swim', 'swimming'), ('skate', 'skating'), ('hike', 'hiking')])
    # TextAreaField类型,段落输入框
    description = TextAreaField('introduction of someone')
    # BooleanField类型,可做CheckBox类型使用,单选框,default='checked'即默认是选上的
    accept_terms = BooleanField('我接收服务条款', default='checked', validators=[DataRequired()])
    # SubmitField按钮
    submit = SubmitField('Register')

wtf自定义验证器validators:

import re

from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import DataRequired, ValidationError


class Mobile:
    """
    自定义手机号码验证器
    """
    regex = re.compile(r'^1[3,4,5,6,7,8,9]]\d{9}$')

    def __init__(self, message=None):
        if message is None:
            self.message = '输入的不是手机号码'
        self.message = message

    def __call__(self, form, field):
        match = self.regex.match(field.data)
        if not match:
            message = self.message
            raise ValidationError(message)
        return match


class RegisterForm(FlaskForm):  # 继承自FlaskForm
    """
    表单属性要和前端传递过来的表单name属性一致,最好也要和数据库里面的字段一致
    """
    phone = StringField(label='手机号码',
                        validators=[
                                    Mobile('手机号码格式错误'),
                                    DataRequired('手机号码不能为空')])
  

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chuntian_tester

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值