默认wtforms.validators中有如下校验器:
__all__ = (
"DataRequired",
"data_required",
"Email",
"email",
"EqualTo",
"equal_to",
"IPAddress",
"ip_address",
"InputRequired",
"input_required",
"Length",
"length",
"NumberRange",
"number_range",
"Optional",
"optional",
"Regexp",
"regexp",
"URL",
"url",
"AnyOf",
"any_of",
"NoneOf",
"none_of",
"MacAddress",
"mac_address",
"UUID",
"ValidationError",
"StopValidation",
)
form中的邮箱可以用Email,密码确认可以用EqualTo等。
本例有种情况,注册用户时,须要填写一个邮箱,向其发送验证码,提交时要检查邮箱和验证码是否配对。要使用自定义校验器。
wtforms.validators都是如下结构:
1 2 3 4 5 6 7 8 9 10 |
class 校验器: def __init__(self, 参数...): # 构造方法,初始化 self.参数 = 参数... def __call__(self, form, field): # 校验方法。form.validate() 或 validate_on_submit()时触发 form即整个表单,首先从中取用到的数据 field即使用了本校验器的控件,取数据 if 某个条件: return # 表示验证结果为真 raise ValidationError(提示信息) # 不满足即抛出一个错误 |
如图中场景,
首先填写邮箱,然后“获取验证码”,后台响应,向邮箱里发送一个验证码,同时把两者作为一个记录保存。
如果填写的邮箱是有效的,用户就能去自己的邮箱查到验证码,手写到表单。
当“注册”时,从表单数据里把邮箱和手写的验证码拿出来,从记录里把这个邮箱的对应验证码提取来,和用户手写的比较。
如果两个验证码匹配相同,则认为邮箱是有效的,以后可用于找回密码啥的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# pip3 install flask-wtf # Successfully installed wtforms-3.0.1 flask-wtf-1.0.1 # https://www.jianshu.com/p/7e16877757f8 # pip3 install email_validator # Successfully installed dnspython-2.2.1 email_validator-1.2.1 # 用在【验证码】控件上的校验器 class EmailValidateCaptcha: def __init__(self, email_field, message=None): self.email_field = email_field # 要关联校验的目标控件,本例关联的是【邮箱】 self.message = message # 验证错误时的提示 def __call__(self, form, field): try: email = form[self.email_field] # 从表单里提取【邮箱】控件 email = email.data # 邮箱 except KeyError as exc: raise ValidationError( field.gettext("Invalid field name '%s'.") % self.email_field # 控件‘id’填写错误时的提示 ) from exc # 以下是自定义的业务。本例是从数据库记录查找这个邮箱的配对验证码, # 然后和用户手动填写的验证码做比对。 # 当数据库中程序自动发送的验证码和用户填写的一致,表示验证成功 cap = util_mysql.getCaptcha(email) # util_mysql是自定义的数据库工具,cap是封装的db.Model if cap.captcha == field.data: print("验证码有效", cap.captcha, field.data) return # 验证成功 raise ValidationError(self.message) # 验证失败 |
在FlaskForm中使用校验器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
from wtforms import StringField, PasswordField, SubmitField, ValidationError from flask_wtf import FlaskForm from wtforms.validators import Length, Email, DataRequired, EqualTo class RegistForm(FlaskForm): # 邮箱,控件名即这个静态变量名‘email’ email = StringField(label="邮箱", validators=[Length(min=3, max=20, message="邮箱格式错误"), Email(message="请输入有效的邮箱"), DataRequired()], render_kw={'placeholder': '输入邮箱'}) # 验证码 captcha = StringField( label="验证码", validators=[ Length(min=6, max=6), EmailValidateCaptcha("email", "填写的验证码无效"), # 自定义校验器("关联的控件的id,即上面的变量名email", "提示") DataRequired() ], render_kw={'placeholder': '输入邮箱中收到的验证码'} ) uname = StringField(label="登录名", validators=[Length(min=6, max=12), DataRequired()], render_kw={'placeholder': '输入登录名'}) pswd = PasswordField(label="密码", validators=[Length(min=6, max=12), DataRequired()], render_kw={'placeholder': '输入密码'}) pswd2 = PasswordField(label="确认密码", validators=[Length(min=6, max=12), EqualTo("pswd", "两次密码不一致"), DataRequired()], render_kw={'placeholder': '再次输入密码'}) submit = SubmitField(label='注册') def validate_email(self, email): print("检查邮箱", email.data) u = util_mysql.getUserByEmail(email.data) # <class 'str'> if u: raise ValidationError(f"邮箱地址 {email.data} 已存在") def validate_uname(self, name): print("检查用户名", name.data) u = util_mysql.getUserByName(name.data) if u: raise ValidationError(f"用户名 {name.data} 已经存在") |
请求处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@bp.route('/regist', methods=["GET", "POST"]) def regist(): # rf = RegistForm() rf = RegistForm(request.form) if request.method == 'POST': if rf.validate_on_submit(): # 这里会执行校验 hash_pswd = generate_password_hash(rf.pswd.data) user = util_mysql.setUser(rf.email.data, rf.uname.data, hash_pswd) if user: flash("注册成功,请登录") return redirect(url_for('user.login')) else: flash(rf.errors) return render_template("regist_html.html", rf=rf) |
页面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<form class="form-horizontal" role="form" action="{{ url_for('user.regist') }}" method="POST"> {{ rf.csrf_token }} <div class="form-group"> <label for="email" class="col-sm-2 control-label">邮箱</label> <div class="col-sm-8"> <input type="email" class="form-control" id="email" name="email" placeholder="请输入邮箱"> </div> </div> <div class="form-group"> <label for="captcha" class="col-sm-2 control-label">验证码</label> <div class="col-sm-6"> <input type="text" class="form-control" id="captcha" name="captcha" placeholder="请输入邮箱中收到的验证码"> </div> <a class="btn btn-default col-sm-2" href="#" role="button" id="btn_captcha">获取验证码</a> <!-- 这里执行ajax请求,后台发送验证码到邮箱 --> </div> <div class="form-group"> <label for="uname" class="col-sm-2 control-label">登录名</label> <div class="col-sm-8"> <input type="uname" class="form-control" id="uname" name="uname" placeholder="请输入登录名"> </div> </div> <div class="form-group"> <label for="pswd" class="col-sm-2 control-label">密码</label> <div class="col-sm-8"> <input type="text" class="form-control" id="pswd" name="pswd" placeholder="请输入密码"> </div> </div> <div class="form-group"> <label for="pswd2" class="col-sm-2 control-label">确认密码</label> <div class="col-sm-8"> <input type="text" class="form-control" id="pswd2" name="pswd2" placeholder="请再次输入密码"> </div> </div> <div class="form-group"> <div class="col-sm-offset-5 col-sm-10"> <button type="submit" class="btn btn-default">注册</button> </div> </div> </form> |
- end
本文由崔维友 威格灵 cuiweiyou vigiles cuiweiyou 原创,转载请注明出处:http://www.gaohaiyan.com/3955.html
承接App定制、企业web站点、办公系统软件 设计开发,外包项目,毕设