使用 Flask 框架寫用戶登錄功能的Demo時碰到的各種坑(一)——創建應用
使用 Flask 框架寫用戶登錄功能的Demo時碰到的各種坑(二)——使用藍圖功能進行模塊化
使用 Flask 框架寫用戶登錄功能的Demo時碰到的各種坑(三)——使用Flask-Login庫實現登錄功能
使用 Flask 框架寫用戶登錄功能的Demo時碰到的各種坑(四)——對 run.py 的調整
使用 Flask 框架寫用戶登錄功能的Demo時碰到的各種坑(五)——實現注冊功能
本次示例的源碼下載:點擊下載
Flask-Login 庫的中文文檔:點擊進入
Flask-Login 庫的新版英文文檔:點擊進入
使用 WTForms 進行表單驗證:點擊進入
一、導入並初始化 Flask-Login 庫
在項目根目錄下的/demo/__init__.py 文件的頭部,import 進 flask_login 庫
from flask_login import LoginManager
在 create_app 函數的前面加入初始化操作:
""" 初始化登錄管理器 """ login_manager = LoginManager() """ 這里的參數格式是:藍圖名稱.函數名 這里是指定了當用戶未登錄的時候,進入需要登錄才能進入的頁面時,會自動跳轉到的頁面。 """ login_manager.login_view = "user.login"
在 create_app 函數中的 app = Flask(__name__) 下面加入:
login_manager.init_app(app)
完整的代碼是:

二、實現登錄模塊
1.增加 MD5 加密公共函數
在該路徑下創建文件並編寫以下代碼:
/demo/common/encrypt.py
def md5(text): import hashlib m = hashlib.md5() t = text.encode(encoding="utf-8") m.update(t) return m.hexdigest()
2.創建用戶模塊
①創建以下目錄
/demo/modules/users
/demo/modules/users/forms
/demo/modules/users/models
/demo/modules/users/templates
②創建 /demo/modules/users/views.py
3.使用 Flask-WTF 庫來驗證提交的表單,點擊查看文檔
在 forms 目錄下 創建 users.py 文件,做登錄表單驗證
/demo/modules/users/forms/users.py
# config=utf-8 from flask_wtf import Form from wtforms import StringField, PasswordField from wtforms.validators import DataRequired, Length, Email class LoginForm(Form): accountNumber = StringField('accountNumber', validators=[DataRequired('賬號不可以是空的'), Length(-1, 200, '賬號的字符數不可以超過 200 個'), Email('賬號只能是郵箱')]) password = PasswordField('password', validators=[DataRequired('密碼不可以是空的'), Length(6, 20, '密碼的字符數只能在 6 - 20 個之間')])
4.創建操作數據庫類
/demo/modules/users/models/users.py
# config=utf-8 from flask_login import UserMixin from demo.common import db class User(db.Model, UserMixin): """ 用戶實體信息 Attributes: id:用戶編號。 accountNumber:賬號。 password:密碼。 name:用戶昵稱。 """ id = db.Column(db.Integer, primary_key=True) accountNumber = db.Column(db.String(200), unique=True) password = db.Column(db.String(50), unique=True) name = db.Column(db.String(20), unique=True) __tablename__ = 'py_user' def __init__(self, user_id=None, account_number=None, password=None, name="anonymous"): """ 初始化用戶信息。 Args: user_id (int): 用戶編號 account_number(string):賬號 password(string):密碼 name (string):昵稱 """ self.id = user_id self.accountNumber = account_number self.password = password self.name = name
db.Model 類是數據庫操作類,實現了數據庫的功能。
UserMixin 是 flask-login 庫提供的一個用戶的基類,定義了 flask-login 的登錄用戶必需使用到的屬性和方法等。
5.在 views.py 中實現具體的登錄功能。
/demo/modules/users/views.py 的完整代碼
# config=utf-8 from flask import Blueprint, request, redirect, url_for from flask import render_template from flask_login import login_user, logout_user from demo import login_manager from demo.common.encrypt import md5 from demo.modules.users.models.users import User from demo.modules.users.forms.users import LoginForm userRoute = Blueprint('user', __name__, url_prefix='/user', template_folder='templates', static_folder='static') @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) @userRoute.route('/login', methods=['GET', 'POST']) def login(): form = LoginForm() if request.method == 'POST': if not form.validate_on_submit(): return render_template('login.html', form=form) user = User.query.filter(User.accountNumber == form.accountNumber.data, User.password == md5(form.password.data)).first() if user: login_user(user) return redirect("/") return render_template('login.html', form=form) @userRoute.route('/logout') def logout(): logout_user() return redirect(url_for('.login'))
其中,要以 @login_manager.user_loader 來描述一個函數,表示 flask-login 庫在獲取當前已登錄的用戶信息時,會該用該函數來獲取:
@login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id))
6.注冊用戶模塊,在 /run.py 文件里增加:
from demo.modules.home.views import homeRoute from demo.modules.users.views import userRoute DEFAULT_MODULES = [homeRoute, userRoute]
/run.py 完整代碼:
# config=utf-8 from demo import create_app from demo.modules.home.views import homeRoute from demo.modules.users.views import userRoute DEFAULT_MODULES = [homeRoute, userRoute] app = create_app('config.py') for module in DEFAULT_MODULES: app.register_blueprint(module) @app.before_request def before_request(): """ 這里是全局的方法,在請求開始之前調用。 其中 flask 有個全局的變量 g,它是和 session 一樣的用途,可以使用它來保存當前用戶的數據 Returns: """ pass if __name__ == '__main__': app.run()
7.創建模板頁面
①創建以下目錄:
/demo/static
/demo/static/js
/demo/static/css
/demo/static/img
分別用於保存 JS、CSS 和圖片。
頁面調用的靜態文件的目錄是應用目錄下的 static 目錄,如果將這些文件放到其它目錄中 ,則無法在頁面中引用。
②下載 jquery 並保存在/static/js/jquery/目錄下
/static/js/jquery/jquery-2.2.0.min.js
③在 /demo/templates/base.html 中引入 jquery:
<!DOCTYPE html> <html lang="cn"> <head> <meta charset="UTF-8"> <title>{% block title %}{% endblock %}</title> <script src="/static/js/jquery/jquery-2.2.0.min.js"></script> {% block head %}{% endblock %} </head> <body> {% block content %}{% endblock %} </body> </html>
④在 /demo/modules/users/templates 目錄創建 login.html 頁面:
{% extends "base.html" %} {% block title %}python flask user page{% endblock %} {% block head %} <style type="text/css"></style> {% endblock %} {% block content %} <form action="{{ url_for('user.login') }}" method="post"> {% if form.errors %} <ul> {% for name, errors in form.errors.items() %} {% for error in errors %} <li>{{ error }}</li> {% endfor %} {% endfor %} </ul> {% endif %} 賬號:{{ form.accountNumber(size=20) }}<label>{{ form.accountNumber.errors[0] }}</label><br/> 密碼:<input name="password" type="password"/><br/> {{ form.hidden_tag() }} <button type="submit">登錄</button> </form> <a href="/">返回</a> {% endblock %}
其中這段表示遍歷輸出所有表單錯誤信息。
{% if form.errors %} <ul> {% for name, errors in form.errors.items() %} {% for error in errors %} <li>{{ error }}</li> {% endfor %} {% endfor %} </ul> {% endif %}
完成了,這幾章只是對在 Flask 使用中的一種補充和記錄,具體還是查文檔。
