flask form表单验证
新建forms.py文件
#!/usr/bin/env python #-*-coding:utf-8-*- #导入模块 from flask_wtf import FlaskForm #FlaskForm 为表单基类 from wtforms import StringField,PasswordField,SubmitField #导入字符串字段,密码字段,提交字段 from wtforms.validators import DataRequired,ValidationError from models import Admin #从models导入模型(表) #定义登录表单,并且需要在视图函数(views.py)中实例化
class LoginForm(FlaskForm): account = StringField( # 标签 label="账号", # 验证器 validators=[ DataRequired('请输入用户名') ], description="账号", # 附加选项,会自动在前端判别 render_kw={ "class":"form-control", "placeholder":"请输入账号!", "required":'required' #表示输入框不能为空,并有提示信息 } ) pwd = PasswordField( # 标签 label="密码", # 验证器 validators=[ DataRequired('请输入密码') ], description="密码",
# 附加选项(主要是前端样式),会自动在前端判别 render_kw={ "class": "form-control", "placeholder": "请输入密码!", "required": 'required' # 表示输入框不能为空 } ) submit = SubmitField( label="登录", render_kw={ "class": "btn btn-primary btn-block btn-flat", } )
视图函数views.py
from . import adminbapp ##导入app
from flask import render_template,redirect,url_for,flash,session,request
from admin.forms import LoginForm #引入forms.py文件
from models import Admin #导入数据库模型
from functools import wraps #导入装饰器模块
from movie_project import db #引入sqlalchemy实例化对象
#登录验证装饰器
def login_required(func):
@wraps(func)
def decorated_function(*args, **kwargs):
if session.get('admin'): #验证session
return func(*args, **kwargs)
else:
return redirect(url_for('admin.login'))
return decorated_function
@adminbapp.route('/login/',methods=['GET','POST']) def login(): forms = LoginForm() #实例化forms if forms.validate_on_submit(): #提交的时候进行验证,如果数据能被所有验证函数接受,则返回true,否则返回false data = forms.data #获取form数据信息(包含输入的用户名(account)和密码(pwd)等信息),这里的account和pwd是在forms.py里定义的 admin = Admin.query.filter_by(name=data["account"]).first() #查询表信息admin表里的用户名信息 if admin == None: flash("账号不存在") #操作提示信息,会在前端显示 return redirect(url_for('admin.login')) elif admin != None and not admin.check_pwd(data["pwd"]): #这里的check_pwd函数在models 下Admin模型下定义 flash("密码错误") return redirect(url_for('admin.login')) session['admin'] = data['account'] #匹配成功,添加session return redirect(request.args.get('next') or url_for('admin.index')) #重定向到首页 return render_template('admin/login.html',form=forms)
数据库模型models.py
class Admin(db.Model): __tablename= 'admin' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100), nullable=False, unique=True) # unique代表不能重复,唯一的 pwd = db.Column(db.String(100), nullable=False) is_super = db.Column(db.SmallInteger) #是否为超级管理员 role_id = db.Column(db.Integer,db.ForeignKey('role.id')) addtime = db.Column(db.DateTime, index=True, default=datetime.datetime.now) adminlogs = db.relationship('Adminlog',backref='admin') adminoption = db.relationship('Oplogs', backref='admin') def __repr__(self): return '<Admin %r>' % self.name
#定义密码验证函数 def check_pwd(self,pwd): from werkzeug.security import check_password_hash #由于密码是加密的,所以要引入相应的加密函数 return check_password_hash(self.pwd,pwd)
前端 login.html
<div class="login-box-body"> {% for msg in get_flashed_messages() %} <!--这里对应视图函数里定义的提示信息 flash--> <p class="login-box-msg" style="color: red;">{{ msg }}</p> <!--信息在前端显示--> {% endfor %} <form method="POST" id="form-data"> <!--使用form,这里可以不用写action--> <div class="form-group has-feedback"> {{ form.account }} <!--常规情况下,这里应该为一个input框,用来定义用户输入,由于在forms里已经定义,这里直接调用就行--> <span class="glyphicon glyphicon-envelope form-control-feedback"></span> {% for err in form.account.errors %} <!--错误信息--> <div class="col-md-12"> <span style="color: red">{{ err }}</span> <!--显示错误信息--> </div> {% endfor %} </div> <div class="form-group has-feedback"> {{ form.pwd }} <!--同上面的用户输入--> <span class="glyphicon glyphicon-lock form-control-feedback"></span> {% for err in form.pwd.errors %} <!--pwd输入错误的提示信息--> <div class="col-md-12"> <font style="color: red">{{ err }}</font> </div> {% endfor %} </div> <div class="row"> <div class="col-xs-8"> </div> <div class="col-xs-4"> {{ form.submit }} <!--提交按钮--> {{ form.csrf_token }} <!--csrftoken必须要写,同时还要设置 app的secret_key--> </div> </div> </form> </div>
配置secret_key
import os app.config['SECRET_KEY'] = os.urandom(24)
实例之会员注册功能
forms.py表单文件
#!/usr/bin/env python #-*-coding:utf-8-*- from flask_wtf import FlaskForm #FlaskForm 为表单基类 from wtforms import StringField,PasswordField,SubmitField #导入字符串字段,密码字段,提交字段 from wtforms.validators import DataRequired,ValidationError,Email,Regexp,EqualTo from models import User class RegistUser(FlaskForm): account = StringField( # 标签 label="昵称", # 验证器 validators=[ DataRequired('请输入昵称') ], description="昵称", # 附加选项,会自动在前端判别 render_kw={ "class":"form-control", "placeholder":"请输入昵称", #"required":'required' #表示输入框不能为空 } ) email = StringField( label="邮箱", # 验证器 validators=[ DataRequired('请输入邮箱'), Email('邮箱格式不正确') #用Email方法验证邮箱格式 ], description="邮箱", # 附加选项,会自动在前端判别 render_kw={ "class": "form-control", "placeholder": "请输入邮箱!", #"required": 'required' # 表示输入框不能为空 } ) phone = StringField( label="手机", # 验证器 validators=[ DataRequired('请输入手机号码'), Regexp("1[3578]\d{9}", message="手机格式不正确") # 用正则匹配手机号码规则 ], description="手机", # 附加选项,会自动在前端判别 render_kw={ "class": "form-control", "placeholder": "请输入手机号码", #"required": 'required' # 表示输入框不能为空 } ) pwd = PasswordField( # 标签 label="密码", # 验证器 validators=[ DataRequired('请输入密码') ], description="密码", # 附加选项,会自动在前端判别 render_kw={ "class": "form-control", "placeholder": "请输入密码!", #"required": 'required' # 表示输入框不能为空 } ) repwd = PasswordField( # 标签 label="确认密码", # 验证器 validators=[ DataRequired('确认密码'), EqualTo('pwd',message="两次密码输入不一致") #判断两次输入的密码是否一致 ], description="确认密码", # 附加选项,会自动在前端判别 render_kw={ "class": "form-control", "placeholder": "确认密码", #"required": 'required' # 表示输入框不能为空 } ) submit = SubmitField( label="注册", render_kw={ "class": "btn btn-success btn-block", } ) # 账号认证,自定义验证器,判断输入的值是否唯一 def validate_name(self, filed): name = filed.data account = User.query.filter_by(name=name).count() if account == 1: raise ValidationError("昵称已经存在") def validate_email(self, filed): emails = filed.data account = User.query.filter_by(email=emails).count() if account == 1: raise ValidationError("邮箱已经注册") def validate_phone(self, filed): phones = filed.data account = User.query.filter_by(phone=phones).count() if account == 1: raise ValidationError("手机号已经注册")
视图函数views.py
@homebapp.route("/register/",methods=['GET','POST']) def register(): form = RegistUser() #实例化form if form.validate_on_submit(): #提交时 data = form.data user = User( name=data['account'], email=data['email'], phone = data['phone'], pwd=generate_password_hash(data['pwd']), uuid = uuid.uuid4().hex ) db.session.add(user) db.session.commit() flash("注册成功",'ok') return render_template("home/register.html",form=form)
models.py
class User(db.Model): __tablename__ ="user" id = db.Column(db.Integer,primary_key=True) name = db.Column(db.String(100),nullable=False,unique=True) #unique代表不能重复,唯一的 pwd = db.Column(db.String(100),nullable=False) email = db.Column(db.String(64),nullable=False,unique=True) phone = db.Column(db.String(11),nullable=False,unique=True) info = db.Column(db.Text) face = db.Column(db.String(100)) #头像 addtime = db.Column(db.DateTime,index=True,default=datetime.datetime.now) uuid = db.Column(db.String(255)) userlogs = db.relationship('UserLog',backref='user') #外键关系关联 comments = db.relationship('Comment',backref='user') movicols = db.relationship('Moviecol', backref='user') def __repr__(self): #定义返回的类型 return '<user %r>' % self.name def check_pwd(self,pwd): #验证密码 from werkzeug.security import check_password_hash return check_password_hash(self.pwd,pwd)
前端register.html
<div class="panel-body"> {% for msg in get_flashed_messages(category_filter=['err']) %} <!--flash信息--> <p style="color: red">{{ msg }}</p> {% endfor %} {% for msg in get_flashed_messages(category_filter=['ok']) %} <p style="color: green">{{ msg }}</p> {% endfor %} <form role="form" method="POST"> <fieldset> <div class="form-group"> <label for="input_name"><span class="glyphicon glyphicon-user"></span> 昵称</label> {{ form.account }} </div> {% for err in form.account.errors %} <div class="col-md-12"> <span style="color: red">{{ err }}</span> </div> {% endfor %} <div class="form-group"> <label for="input_email"><span class="glyphicon glyphicon-envelope"></span> 邮箱</label> {{ form.email }} </div> {% for err in form.email.errors %} <div class="col-md-12"> <span style="color: red">{{ err }}</span> </div> {% endfor %} <div class="form-group"> <label for="input_phone"><span class="glyphicon glyphicon-phone"></span> 手机</label> {{ form.phone }} </div> {% for err in form.phone.errors %} <div class="col-md-12"> <span style="color: red">{{ err }}</span> </div> {% endfor %} <div class="form-group"> <label for="input_password"><span class="glyphicon glyphicon-lock"></span> 密码</label> {{ form.pwd }} </div> {% for err in form.pwd.errors %} <div class="col-md-12"> <span style="color: red">{{ err }}</span> </div> {% endfor %} <div class="form-group"> <label for="input_repassword"><span class="glyphicon glyphicon-lock"></span> 确认密码</label> {{ form.repwd }} </div> {% for err in form.repwd.errors %} <div class="col-md-12"> <span style="color: red">{{ err }}</span> </div> {% endfor %} {{ form.csrf_token }} {{ form.submit }} </fieldset>