新建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>