上一篇講完了可以在客戶端及伺服端雙向通訊的 WebSocket ,這篇要講的是有關登入系統的 Flask-Login。
開始使用前當然要先安裝對吧,這邊開一個新的專案,還是使用 pip 來安裝。
$ pipenv install flask-login
等它跑完就安裝好了。接著來看一下架構吧(其實也沒啥架構啦)。
ithome_login
├── app.py
├── config.py # 依舊還是放有關設定檔的東西
├── db.py # 雖然它看起來很像資料庫,等一下你就知道完全不是這麼一回事了
├── Pipfile # 這個跟下面那個舊不用我說了吧
└── Pipfile.lock
先來看一下長得很像資料庫的東西。
db.py
# 下面這坨是我懶得弄資料庫,所以假裝他是資料庫裡記錄資料就好
class Database:
# users 是類似資料庫裡的紀錄
users = {
"0": {
"email": "test01@gmail.com",
"password": "123"
},
"1": {
"email": "test02@gmail.com",
"password": "456"
}
}
user_profile = {
"0": {
"username": "test01"
},
"1": {
"username": "test02"
}
}
# 從資料庫裡抓取這個使用者
@classmethod
def get_data(self, email):
for index, data in self.users.items():
if email in data['email']:
return {"id": index, **self.users[index]}
return None
# 從資料庫裡抓取這個使用者
@classmethod
def get(self, user_id):
return self.user_profile[user_id]
然後來看一下 app.py
from flask import Flask, redirect, request, url_for
# 加上下面這行
from flask_login import LoginManager, UserMixin, login_user, logout_user, current_user, login_required
import config
from db import Database
app = Flask(__name__)
app.config.from_object(config.DevelopmentConfig)
# 初始化 LoginManager
login_manager = LoginManager(app)
# 如果跳到需要先登入才能看的頁面,會自動轉到叫做 login 的 function(也可以自己改)。
login_manager.login_view = "login"
# 繼承 UserMixin 類,可以不設定,可做為 ORM(物件關聯對映) 的東西(我真的不知道怎麼說)
class User(UserMixin):
pass
# 提供使用者詳細資料,必須設定,current_user 會用到
@login_manager.user_loader
def load_user(user_id):
user_data = Database.get(user_id)
if user_data is None:
return None
user = User()
user.username = user_data['username']
return user
# 登入頁面
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return '''
<form action='login' method='POST'>
<input type='text' name='email' id='email' placeholder='email'/>
<input type='password' name='password' id='password' placeholder='password'/>
<input type='submit' name='submit'/>
</form>
'''
elif request.method == 'POST':
email = request.values.get('email', None)
password = request.values.get('password', None)
user_data = Database.get_data(email)
if (user_data is not None) and (password == user_data['password']):
# 主要登入部分
user = User()
user.id = user_data['id']
login_user(user)
return redirect(url_for('home'))
else:
return "Account or Password are wrong"
else:
return 'Error'
# 登入後畫面
@app.route('/home')
@login_required # 必須登入才能夠看到的畫面就加上這行,沒登入會自動跳轉到 login_view
def home():
if current_user.is_active:
return 'Welcome ' + current_user.username + '<br /><a href=' + url_for('logout') + '><button>Logout</button></a>'
# 登出畫面
@app.route('/logout')
def logout():
logout_user()
return 'Logged out'
if __name__ == "__main__":
app.run()
是不是還不太懂在幹嘛,其實大概只有 5 個東西要注意。
login_user: 在 Session 中紀錄登入的使用者。
logout_user: 在 Session 中刪除紀錄的使用者。
user_loader: 去資料庫抓使用者詳細資料。
current_user: 使用 login_user 紀錄的使用者資料透過 user_loader 抓取使用者詳細資料。
class User(UserMixin): 有關使用者實體的資料(我真的不太會解釋啦)。
大概就這樣,接著直接啟動 Flask 然後用瀏覽器看一下效果吧。
首先是登入畫面
然後是登入後的畫面
最後是登出畫面
那麼就大概這樣,Flask-Login 簡單來說是個很方便的插件,剛開始看起來可能會覺得有點複雜,不過多嘗試幾次就可以懂了(話說上面的那 5 個東西我也是看了像是天書一樣的源碼加上各種 try-error 才好不容易稍微理解,加上我那漸漸不行的中文能力,所以解釋起來可能不是很精確)。
大家掰~掰~