使用flask_sqlalchemy、flask_login、flask_admin模擬最簡單的管理員後臺
阿新 • • 發佈:2022-03-10
一、功能描述
使用flask_sqlalchemy、flask_login、flask_admin,模擬管理後臺的登入認證過程。目的是隻讓已經登入的使用者訪問index和admin頁面。
二、功能及效果
1、 訪問index或者後臺admin頁面,自動重定向到首頁
2、登入賬號,如果資料庫裡面檢索到記錄,登入,並重定向到管理頁面。同時,可以訪問index頁面了,也可以讓管理員管理已經註冊到admin的model
3、 使用登出連結之後,重新返回登入頁面
三、完整程式碼
HTML
{% extends 'BASE.html' %} {% block Content %} <h1>lOGIN</h1> {% for message in get_flashed_messages() %} <p>{{ message }}</p> {% endfor %} <form action="{{ url_for('login') }}" method="post"> {% for item in form %} <p>{{ item.label }}</p> <p>{{ item }}</p> {% endfor %} <p> <input type="submit" value="提交"> </p> <p> <a href="{{ url_for('logout') }}">登出</a> </p> </form> {% endblock %}
PYTHON
from flask import Flask,render_template,redirect,url_for,request,flash from flask_sqlalchemy import SQLAlchemy from flask_admin import Admin,AdminIndexView,menu from flask_admin.contrib.sqla import ModelView from flask_login import LoginManager,UserMixin,login_user,current_user,logout_user,login_required from flask_wtf import Form from wtforms import StringField,PasswordField app = Flask("flask_login_admin") app.secret_key = "mykey" app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///TestDB.sqlite3" # 使用flask_sqlalchemy,用orm建立使用者資料庫Model,注意一定要繼承UserMixin類 db = SQLAlchemy(app=app) class Admin_Table(db.Model,UserMixin): id = db.Column(db.Integer,primary_key=True) username = db.Column(db.String(20),unique=True) password = db.Column(db.String(20)) login_manager = LoginManager(app=app) # 你必須提供一個 user_loader 回撥。這個回撥用於從會話中儲存的使用者 ID 重新載入使用者物件。它應該接受一個使用者的 unicode ID 作為引數,並且返回相應的使用者物件。 @login_manager.user_loader def user_log(user_id): return Admin_Table.query.get(user_id) # 使用@login_required裝飾器的時候,如果沒有登入,預設返回錯誤401,如果使用了這個裝飾器,可以設定成重定向到登入頁面 @login_manager.unauthorized_handler def unauthorized_handler(): flash("請先登入!") return redirect(url_for("login")) # 使用flask_wtf在前端建立登入表單 class Login_Form(Form): username = StringField("使用者名稱") password = PasswordField("密碼") @app.route("/login/",endpoint="login",methods=["GET","POST"]) def login(): if request.method == "GET": # 如果已經登入的話,直接重定向到admin頁面 if current_user.is_authenticated: return redirect(url_for("admin.index")) else: form = Login_Form() return render_template("login.html",form=form) elif request.method == "POST": form = Login_Form(request.form) if form.validate(): username = form.username.data password = form.password.data # 檢查資料庫裡面是否有對應的賬密 user = Admin_Table.query.filter(Admin_Table.username == username,Admin_Table.password == password).first() if user: # 如果資料庫裡面有記錄,將當前使用者的orm物件新增到flask_login裡面,之後current_user.is_authenticated返回的就是True了 login_user(user) flash("登入成功!") return redirect(url_for("admin.index")) flash("沒有相關的使用者名稱和密碼!") return render_template("login.html",form=form) # 注意,login_required一下要放在route裝飾器的下面,如果沒有登入,自動使用unauthorized_handler()重定向到login頁面 @app.route("/",endpoint="index") @login_required def index(): return render_template("index.html") # 用於登出的檢視函式,為了保證只有在登入狀態下才能logout,所以也要加一個@logout_required裝飾器 @app.route("/logout/",endpoint="logout") @login_required def logout(): logout_user() flash("登出成功") return redirect(url_for("login")) # 如果只對flask_admin註冊的其中一個檢視函式進行認證,繼承ModelView類,然後改寫裡面的方法就行了,也就是說在沒有認證的前提下,還是可以訪問/admin/路徑,只不過不顯示註冊的檢視函式 class MyModelView(ModelView): def is_accessible(self): return current_user.is_authenticated def inaccessible_callback(self, name, **kwargs): return redirect(url_for("login")) # 對整個admin後臺進行認證,沒有登入認證的話,訪問/admin/就直接重定向到login頁面,和上面的MyModelView類選一個即可實現功能 class MyAdminIndexView(AdminIndexView): def is_accessible(self): return current_user.is_authenticated def inaccessible_callback(self, name, ** kwargs): flash("請先登入!") return redirect(url_for("login")) # 在admin頁面的導航添加註銷按鈕 class LogoutMenu(menu.MenuLink): def is_accessible(self): return current_user.is_authenticated admin = Admin(app=app,name="Admin測試",endpoint="admin",template_mode="bootstrap4",index_view=MyAdminIndexView()) admin.add_view(MyModelView(Admin_Table,db.session)) admin.add_link(LogoutMenu(name="Logout",endpoint="logout")) if __name__ == '__main__': db.create_all() app.run(debug=True)