1. 程式人生 > >Flask博客類登錄註冊驗證模塊代碼(十四)

Flask博客類登錄註冊驗證模塊代碼(十四)

extent down rms 地址 generate targe 文件系統 退出 生產

1 文件系統

blog  #博客類             
    App
        forms     #表單
            __init__.py
            user.py
        models     #模型
            __init__.py
            user.py
        static      #靜態文件
        templates   #模板
            common  #基類模板
                base.html
            email  #郵件
                email.html
            errors  #錯誤
error.html main #主頁 index.html user #用戶登錄註冊 login.html register.html views #視圖藍本 __init__.py main.py user.py __init__.py email.py #郵件 extensions.py #擴展庫
settings.py #系統配置 migrations #遷移文件 manage.py #啟動文件

2 forms目錄下

#__init__.py
from .user import Register,Login

#user.py
from flask_wtf import FlaskForm
from wtforms import SubmitField,StringField,PasswordField,BooleanField,ValidationError
from App.models import User
from wtforms.validators import
DataRequired,Email,Length,EqualTo class Register(FlaskForm): username = StringField(‘用戶名‘,validators=[DataRequired(message=‘用戶名不能為空...‘),Length(min=6,max=12,message=‘長度為6-12位‘)],render_kw={‘placeholder‘:‘請輸入用戶名...‘,‘maxlength‘:12}) password = PasswordField(‘密碼‘,validators=[DataRequired(message=‘密碼不能為空‘),Length(min=6,max=12,message=‘長度為6-12位‘),EqualTo(‘confirm‘,message=‘倆次密碼不一致‘)],render_kw={‘placeholder‘:‘請輸入密碼...‘,‘maxlength‘:12}) confirm = PasswordField(‘密碼‘,validators=[DataRequired(message=‘密碼不能為空‘),Length(min=6,max=12,message=‘長度為6-12位‘)],render_kw={‘placeholder‘:‘請輸入確認密碼...‘,‘maxlength‘:12}) email = StringField(‘郵箱‘,validators=[Email(message=‘請輸入正確的郵箱‘)],render_kw={‘placeholder‘:‘請輸入郵箱...‘,‘maxlength‘:30}) submit = SubmitField(‘註冊‘) # 自定義驗證器 用戶名是否存在 def validate_username(self, field): if User.query.filter(User.username == field.data).first(): raise ValidationError(‘該用戶已註冊!!!‘) # 自定義驗證器 郵箱是否存在 def validate_email(self, field): if User.query.filter(User.email == field.data).first(): raise ValidationError(‘該郵箱已註冊!!!‘) class Login(FlaskForm): username = StringField(‘用戶名‘,validators=[DataRequired(message=‘用戶名不能為空...‘), Length(min=6, max=12, message=‘長度為6-12位‘)],render_kw={‘placeholder‘: ‘請輸入用戶名...‘, ‘maxlength‘: 12}) password = PasswordField(‘密碼‘,validators=[DataRequired(message=‘密碼不能為空‘),Length(min=6, max=12, message=‘長度為6-12位‘)],render_kw={‘placeholder‘: ‘請輸入密碼...‘, ‘maxlength‘: 12}) remember = BooleanField(‘記住我‘) submit = SubmitField(‘登錄‘)

3 models目錄下

#__init__.py
from .user import User

#user.py
from App.extensions import db
from werkzeug.security import generate_password_hash,check_password_hash
from itsdangerous import TimedJSONWebSignatureSerializer as Seralize
from flask import current_app
from flask_login import UserMixin
from App.extensions import login_manager

class User(UserMixin,db.Model):
    __tablename__ = ‘user‘
    id = db.Column(db.Integer,primary_key=True)
    username = db.Column(db.String(12),index=True)
    password_hash = db.Column(db.String(128))
    sex = db.Column(db.Boolean,default=True)
    age = db.Column(db.Integer)
    email = db.Column(db.String(40))
    icon = db.Column(db.String(70),default=‘default.jpg‘)
    #當期賬戶激活狀態
    confirm = db.Column(db.Boolean,default=False)

    @property
    def password(self):
        raise ValueError
    #密碼設置為hash
    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    #生成token的方法
    def generate_token(self):
        s = Seralize(current_app.config[‘SECRET_KEY‘])
        return s.dumps({‘id‘:self.id})

    #檢測token的方法
    @staticmethod
    def check_token(token):
        s = Seralize(current_app.config[‘SECRET_KEY‘])
        # print(s)
        #從當前的token中拿出字典
        try:
            id = s.loads(token)[‘id‘]
        except:
            return False
        #獲取id對應的user數據
        u = User.query.get(id)
        if not u:
            return False
        if not u.confirm:
            print(u.confirm)
            u.confirm = True
            print(u.confirm)
            db.session.add(u)
        return True
    #驗證密碼
    def check_password_hash(self,password):
        return check_password_hash(self.password_hash,password)

#登錄認證的回調  保持數據的一致性
@login_manager.user_loader
def user_loader(uid):
    return User.query.get(int(uid))

3 views目錄

#__init__.py
from .user import user
from .main import main
BluePrint = [
    (user,‘‘),
    (main,‘‘)
]
def config_blueprint(app):
    for blueprint,prefix in BluePrint:
        app.register_blueprint(blueprint,url_prefix=prefix)
        
#main.py
from flask import Blueprint,render_template

main = Blueprint(‘main‘,__name__)
@main.route(‘/‘)
def index():
    return render_template(‘main/index.html‘)

#user.py
from flask import Blueprint,render_template,flash,redirect,url_for
from App.models import User
from App.forms import Register,Login
from App.extensions import db
from App.email import send_mail
from flask_login import login_user,logout_user,current_user

user = Blueprint(‘user‘,__name__)
#註冊
@user.route(‘/register/‘,methods=[‘GET‘,‘POST‘])
def register():
    form = Register()
    if form.validate_on_submit():
        #實例化user模型類
        u = User(username=form.username.data,password=form.password.data,email=form.email.data)
        db.session.add(u)
        db.session.commit()
        #生成token
        token = u.generate_token()
        #發送郵件
        send_mail(‘郵件激活‘,form.email.data,‘activate‘,username=form.username.data,token=token)
        flash(‘註冊成功請去郵箱中激活‘)
        #跳轉到登錄頁面
        return redirect(url_for(‘user.login‘))
    return render_template(‘user/register.html‘,form=form)

@user.route(‘/activate/<token>/‘)
def activate(token):
    if User.check_token(token):
        flash(‘激活成功 請登錄‘)
        return redirect(url_for(‘user.login‘))
    else:
        flash(‘激活失敗‘)
        return redirect(url_for(‘main.index‘))

#登錄
#加一個時間的驗證  如果輸入錯誤超過三次  把激活改為False
@user.route(‘/login/‘,methods=[‘GET‘,‘POST‘])
def login():
    form = Login()
    if form.validate_on_submit():
        u = User.query.filter_by(username=form.username.data).first()
        if not u:
            flash(‘該用戶不存在‘)
        elif not u.confirm:
            flash(‘該用戶還沒激活!!!‘)
        elif u.check_password_hash(form.password.data):
            flash(‘登錄成功!‘)
            login_user(u,remember=form.remember.data)
            return redirect(url_for(‘main.index‘))
        else:
            flash(‘請輸入正確的密碼‘)
    return render_template(‘user/login.html‘,form=form)

#退出登錄
@user.route(‘/logout/‘)
def logout():
    logout_user()
    flash(‘退出成功!‘)
    return redirect(url_for(‘main.index‘))

4 APP應用下

__init__.py
from flask import Flask,render_template
from App.settings import config
from App.extensions import config_extentions
from App.views import config_blueprint
#利用工廠函數統一在調用時綁定
def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(config[config_name])
    config_extentions(app)
    config_blueprint(app)
    errors(app)
    return app
#錯誤頁面
def errors(app):
    @app.errorhandler(404)
    def page_not_found(e):
        return render_template(‘errors/error.html‘,error=e)
    @app.errorhandler(500)
    def server_error(e):
        return render_template(‘errors/error.html‘, error=e)

email.py

from flask import render_template,current_app
from flask_mail import Message
from threading import Thread
from App.extensions import mail

def async_send_mail(app,msg):
    #獲取文件上下文
    with app.app_context():
        mail.send(message=msg)
#定義發送郵件函數
def send_mail(subject,to,tem,**kwargs):
    app = current_app._get_current_object()
    msg = Message(subject=subject, recipients=[to], sender=app.config[‘MAIL_USERNAME‘])
    msg.html = render_template(‘email/‘+tem+‘.html‘,**kwargs)
    send = Thread(target=async_send_mail,args=(app,msg))
    send.start()

extensions.py

from flask_bootstrap import Bootstrap
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
from flask_mail import Mail
#擴展庫的實例化
bootstrap = Bootstrap()
db = SQLAlchemy()
migrate = Migrate(db=db)
login_manager = LoginManager()
mail = Mail()
#統一進行app的初始化操作
def config_extentions(app):
    bootstrap.init_app(app)
    db.init_app(app)
    migrate.init_app(app=app)
    login_manager.init_app(app=app)
    mail.init_app(app)

    login_manager.login_view = ‘user.login‘
    login_manager.login_message = ‘請登錄在訪問‘
    login_manager.session_protection = ‘strong‘

settings.py

import os
#所有環境配置的基類
class Config:
    SECRET_KEY = ‘xiafsadwsda‘
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    SQLALCHEMY_COMMIT_ON_TEARDOWN = True
    MAIL_SERVER =  os.environ.get(‘MAIL_SERVER‘,‘smtp.163.com‘)
    MAIL_USERNAME = os.environ.get(‘MAIL_USERNAME‘,[email protected])
    MAIL_PASSWORD = os.environ.get(‘MAIL_PASSWORD‘,‘mm22kk11‘)

#測試配置
class TestingConfig(Config):
    SQLALCHEMY_DATABASE_URI = ‘mysql+pymysql://root:[email protected]:3306/testing‘

#開發配置
class DevelopmentConfig(Config):
    SQLALCHEMY_DATABASE_URI = ‘mysql+pymysql://root:[email protected]:3306/blogModel‘

#生產配置
class ProductionConfig(Config):
    SQLALCHEMY_DATABASE_URI = ‘mysql+pymysql://root:[email protected]:3306/development‘
#一個配置的字典
config = {
    ‘development‘:DevelopmentConfig,
    ‘production‘:ProductionConfig,
    ‘test‘:TestingConfig,
    ‘default‘:DevelopmentConfig
}

manage.py

from flask_script import Manager
from App import create_app
from flask_migrate import MigrateCommand
#調用創建create_app函數
app = create_app(‘default‘)
manager = Manager(app)
manager.add_command(‘db‘,MigrateCommand)

if __name__ == ‘__main__‘:
    manager.run()

html頁面的代碼比較多,有需要的可以訪問源碼地址,感謝閱讀!!

GitHub源碼地址:https://github.com/whyjust/blog

Flask博客類登錄註冊驗證模塊代碼(十四)