建立一個項目以後,須要在手動建立幾個包(含有__init__.py文件的目錄)和文件html
一、在主目錄下建立配置文件:config.py前端
二、在主目錄下建立擴展文件:exts.pypython
三、在主目錄下建立管理文件(供在命令行使用):manage.pymysql
四、在主目錄下建立app包,在app包下再建立cms包管理後臺的文件sql
五、在cms包下建立views.py文件管理視圖函數、models.py文件管理數據庫模型、forms.py文件管理表單驗證數據庫
在配置文件下配置密鑰、數據庫鏈接等(配置文件的全部變量必須是所有大寫)flask
主目錄/config.py import os SECRET_KEY = os.urandom(24) DEBUG = True SQLALCHEMY_DATABASE_URI = "mysql://你的數據庫用戶名:用戶密碼@127.0.0.1:3306/數據庫名稱" SQLALCHEMY_TRACK_MODIFICATIONS = False
Flask框架封裝了數據庫的一些操做,將其置爲擴展包falsk-sqlalchemy,只須要實例化SQLAlchemy對象瀏覽器
主目錄/exts.py from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy()
在入口文件定義一個建立app的方法,供藍圖使用,這裏說的藍圖就是app包下的包(模塊).因爲本篇博客實現的是後臺登陸,即涉及表單驗證,因此須要防止csrf注入攻擊安全
主目錄/app.py from flask import Flask from flask_wtf import CSRFProtect from apps.cms import bp as cms_bp from apps.cms import login_manager as cms_login_manager import config from exts import db def create_app(): """ 主入口文件建立app,供其餘藍圖使用 :return: 返回一個app """ app = Flask(__name__) # 防止csrf注入攻擊 CSRFProtect(app) # 註冊藍圖模塊 app.register_blueprint(cms_bp, url_prefix="/cms") # 導入配置文件 app.config.from_object(config) # 數據庫db初始化app db.init_app(app) # 後臺登陸login_manager初始化app cms_login_manager.init_app(app) return app if __name__ == '__main__': app = create_app() app.run()
cms包下有一個初始化py文件,通常是用來供導包的session
主目錄/app/cms/__init__.py from .views import bp from .views import login_manager
在藍圖中的模型文件中建立用戶模型,即在cms包下的models.py文件建立。建立模型已做詳細說明
主目錄/app/cms/models.py from exts import db from datetime import datetime from werkzeug.security import generate_password_hash, check_password_hash from flask_login import UserMixin class CMSUser(db.Model, UserMixin): """ 定義一個類名,系統將類轉換爲表格,表名爲cms_user 定義類的屬性就是表格的字段名 爲了安全性,能夠將用戶表的password屬性置爲保護屬性如 _password 爲了方便用戶操做保護屬性像操做普通屬性同樣,須要裝飾 _password 在設置密碼的過程當中,須要對密碼加密——>調用generate_password_hash() 另外定義一個校驗密碼的方法check_password() 在校驗密碼的過程當中,須要對密碼解密——>調用check_password_hash() """ __tablename__ = "cms_user" id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(50), nullable=False) _password = db.Column(db.String(100), nullable=False) email = db.Column(db.String(50), nullable=False, unique=True) join_time = db.Column(db.DateTime, default=datetime.now) def __init__(self, username, password, email): self.username = username self.password = password self.email = email @property def password(self): return self._password @password.setter def password(self, raw_password): """ 設置密碼 :param raw_password: 前端後臺傳入的密碼參數 :return:沒有返回值 """ self._password = generate_password_hash(raw_password) def check_password(self, raw_password): """ 校驗密碼,將數據庫的存入的密碼解密以後再與傳入的密碼參數匹配 :param raw_password: 前端後臺傳入的密碼參數 :return: True or False """ result = check_password_hash(self.password, raw_password) return result
Flask框架不像Django框架能夠直接使用命令行生成遷移文件並同步到數據庫當中,Flask框架須要藉助flask_script包下的管理類Manager、flask_migrate包下的遷移類Migrate和一些相關的遷移命令類MigrateCommand。
一、先獲取app對象
二、再實例化一個管理對象manage,綁定到app上
三、將app應用與db數據庫對象綁定到遷移類中
四、將遷移文件中用到的命令封裝成 db (這個db不是db數據庫對象),調用add_command()添加到manage中
五、完成上面幾個文件的代碼填充,能夠在命令行中輸入相關命令,這裏不作解釋,代碼中有提示
主目錄/manage.py from flask_script import Manager from flask_migrate import Migrate, MigrateCommand from app import create_app from exts import db from apps.cms import models as cms_models # 獲取模型中定義的類 CMSUser = cms_models.CMSUser app = create_app() # 定義Manager類實例化對象 manage = Manager(app) # 將app應用與db數據庫綁定到遷移文件中 Migrate(app, db) # 將遷移文件用到的命令換成db開頭(manage.py文件能夠自定義命令)添加到manage中 manage.add_command("db", MigrateCommand) @manage.option("-u", "--username", dest="username") @manage.option("-p", "--password", dest="password") @manage.option("-e", "--email", dest="email") def create_cms_user(username, password, email): """ 自定義建立後臺用戶的命令,在cmd命令行中輸入相似於以下命令,便可添加用戶:(在虛擬環境下) python manage.py db create_cms_user -u 用戶名 -p 密碼 -e 郵箱地址 :param username: :param password: :param email: :return: 返回一提示消息 """ user = CMSUser(username=username, password=password, email=email) db.session.add(user) db.session.commit() print("cms用戶添加成功") if __name__ == "__main__": manage.run()
對前端後臺登陸的表單提供的數據進行驗證,須要藉助flask_wtf包下的FlaskForm類
主目錄/app/cms/forms.py from flask_wtf import FlaskForm from wtforms import StringField, IntegerField from wtforms.validators import DataRequired, Length, Email class LoginForm(FlaskForm): email = StringField(validators=[DataRequired(message="請輸入郵箱地址"), Email(message="請輸入正確的郵箱格式")]) password = StringField(validators=[Length(6, 20, message="請輸入正確格式的密碼")]) remember = IntegerField()
這裏沒有設置頁面,就不渲染頁面,直接返回一個字符串標識一下便可。渲染頁面作的事情通常是在views.py中實現的,這個views.py文件採用了兩種方式:視圖函數和基於調度方法的類視圖。
這裏有必要提一下:對於沒有登陸的行爲,是不能訪問主頁(這裏是指登陸成功以後跳轉的頁面)。實現這一要求,咱們須要從flask_login包下導入login_user、logout_user、login_required、LoginManager
一、和上面同樣,實例化LoginManager對象login_manager也要初始化app(在入口文件app.py會有一行代碼)
二、對於沒有登陸的用戶咱們須要給一個重定向(咱們把它做爲重定向)。這個實例化對象有一個屬性login_view,給其賦值(值是一個url)
三、最重要的一點:調用了login_user()會自動生成一個session值,調用了logout_user()會自動刪除這一個session值。這個session值是經過裝飾器@login_manager.user_loader修飾的函數生成
四、視圖函數和類視圖已在代碼中做詳細說明
主目錄/app/cms/views.py from flask import Blueprint, views, render_template, request, session, redirect, url_for from flask_login import login_required, LoginManager from flask_login import login_user from .forms import LoginForm from .models import CMSUser # 指定沒有登陸時重定向的頁面,須要將LoginManager的實例化對象初始化app(在入口文件中) login_manager = LoginManager() login_manager.login_view = "cms.login" # 定義藍圖對象 bp = Blueprint("cms", __name__) @bp.route("/") @login_required def index(): return "cms index" class LoginView(views.MethodView): """ get方法對應前端後臺的get請求,主要是渲染頁面 post方法對應前端後臺的post請求: 一、先驗證用戶的輸入是否符合表單驗證的要求,若是不符合要求,則返回具體的錯誤 二、先經過郵箱查找用戶並經過查找的用戶密碼與後臺表格密碼進行驗證,若是沒有找到,返回郵箱或者密碼錯誤 三、匹配成功則經過login_user(user)自動保存session值 四、經過獲取前端後臺的remember值給session定義過時時間,默認是瀏覽器會話關閉 """ def get(self, message=None): return render_template("cms/cms_login.html", message=message) def post(self): form = LoginForm(request.form) if form.validate(): email = form.email.data password = form.password.data remember = form.remember.data user = CMSUser.query.filter(CMSUser.email == email).first() if user and user.check_password(password): # 自動生成一個session值 login_user(user) if remember: # 設置session的過時時間,默認爲31天 session.permanent = True return redirect(url_for("cms.index")) return redirect(url_for("cms.index")) else: return self.get(message="郵箱或者密碼錯誤") else: message = form.errors.popitem()[1][0] return self.get(message=message) bp.add_url_rule("/login", view_func=LoginView.as_view("login")) @login_manager.user_loader def load_user(user_id): """ 後臺用戶類必須繼承UserMixin,以防用戶表沒有定義校驗的字段,如:is_active等 :param user_id: :return: """ return CMSUser.query.get(user_id)
前臺用當前登陸的用戶的相關信息的幾種方式:
一、能夠在模板上(頁面)使用當前登錄用戶的代理current_user(具體值就加「點屬性」)
二、在views.py文件中將登陸的用戶信息保存到 g 對象中(這個 g 對象很重要,並且使用很方便)
這樣一個後臺登陸實現已經實現了,能幫助到你們,點個贊,加個關注,誠摯感謝!