python結(jié)合QT實現(xiàn)簡單的圖書管理系統(tǒng)
適用對象:Python 初學(xué)者、剛接觸面向?qū)ο蠛?GUI 編程的同學(xué)
目標(biāo):帶你從零理解一個基于 PyQt5 的小型圖書管理系統(tǒng)架構(gòu)與實現(xiàn)細節(jié)
一、項目整體結(jié)構(gòu)概覽
我們這個系統(tǒng)由以下幾個核心模塊組成:
| 模塊 | 功能 |
|---|---|
| model/ | 數(shù)據(jù)模型(User, Book, Role, Permission) |
| dao/ | 數(shù)據(jù)訪問層(Database) |
| controller/ | 控制邏輯(用戶、圖書、權(quán)限控制) |
| view/ | 用戶界面(登錄、注冊、不同角色主窗口) |
| main.py | 程序入口 |
二、數(shù)據(jù)模型(Model)
1. 角色定義 ——role.py
class Role:
ADMIN = "admin"
TEACHER = "teacher"
STUDENT = "student"
- 這里用類變量模擬“枚舉”,避免魔法字符串。
- 后續(xù)所有判斷角色的地方都用
Role.ADMIN而不是"admin",更安全、可讀性高。
2. 權(quán)限定義 ——permission.py
class Permission:
ADD_BOOK = "add_book"
DELETE_BOOK = "delete_book"
IMPORT_BOOK = "import_book"
EXPORT_BOOK = "export_book"
同樣是枚舉思想,定義系統(tǒng)支持的所有操作權(quán)限。
3. 用戶模型 ——user.py
class User:
def __init__(self, id, username, role):
self.id = id
self.username = username
self.role = role
封裝用戶基本信息,用于在程序中傳遞身份。
4. 圖書模型 ——book.py
class Book:
def __init__(self, id, title, author, isbn, category):
self.id = id
self.title = title
self.author = author
self.isbn = isbn
self.category = category
雖然當(dāng)前代碼中沒直接用到 Book 類(因為數(shù)據(jù)庫返回的是字典),但保留它為未來擴展打基礎(chǔ)。
三、數(shù)據(jù)訪問層(DAO)——database.py
import sqlite3
class Database:
def __init__(self, db_name="library.db"):
self.conn = sqlite3.connect(db_name)
self.conn.row_factory = sqlite3.Row # ← 關(guān)鍵!讓結(jié)果像字典一樣訪問
self.init_tables()
def init_tables(self):
# 創(chuàng)建 users 表
self.conn.execute("""
CREATE TABLE IF NOT EXISTS users(
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE,
password TEXT,
role TEXT
)
""")
# 創(chuàng)建 books 表
self.conn.execute("""
CREATE TABLE IF NOT EXISTS books(
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
author TEXT,
isbn TEXT,
category TEXT
)
""")
self.conn.commit()
def execute(self, sql, params=()):
cursor = self.conn.cursor()
cursor.execute(sql, params)
self.conn.commit()
return cursor
重點說明:
- 使用 SQLite 內(nèi)嵌數(shù)據(jù)庫,無需額外安裝服務(wù)。
row_factory = sqlite3.Row讓查詢結(jié)果可以通過row["username"]方式訪問,而不是row[1],極大提升可讀性。execute方法統(tǒng)一處理 SQL 執(zhí)行 + 提交,避免忘記 commit。
四、用戶控制器 ——user_controller.py
import hashlib
from dao.database import Database
from model.user import User
from model.role import Role
class UserController:
def __init__(self):
self.db = Database()
self.ensure_admin() # 確保 admin 用戶存在
def hash_password(self, password):
return hashlib.sha256(password.encode()).hexdigest()
def ensure_admin(self):
cursor = self.db.execute("SELECT * FROM users WHERE username=?", ("admin",))
if cursor.fetchone() is None:
self.register("admin", "123456", Role.ADMIN)
def register(self, username, password, role):
if not username or not password:
raise Exception("用戶名或密碼不能為空")
self.db.execute("""
INSERT INTO users(username, password, role)
VALUES (?, ?, ?)
""", (username, self.hash_password(password), role))
def login(self, username, password):
cursor = self.db.execute("SELECT * FROM users WHERE username=?", (username,))
user = cursor.fetchone()
if user and user["password"] == self.hash_password(password):
return User(user["id"], user["username"], user["role"])
return None
關(guān)鍵點解析:
- 密碼安全:使用
hashlib.sha256對密碼哈希,絕不存明文密碼。 - 自動創(chuàng)建管理員:第一次運行時自動創(chuàng)建
admin / 123456賬號,方便測試。 - 登錄驗證:比對哈希后的密碼,成功則返回
User對象,失敗返回None。 - 異常處理:注冊時空用戶名/密碼會拋出異常(后續(xù) UI 會捕獲并提示)。
注意:123456 是弱密碼,實際項目應(yīng)要求強密碼或首次登錄改密。
五、權(quán)限管理器 ——permission_manager.py
from model.role import Role
from model.permission import Permission
class PermissionManager:
ROLE_PERMISSIONS = {
Role.ADMIN: [
Permission.ADD_BOOK,
Permission.DELETE_BOOK,
Permission.IMPORT_BOOK,
Permission.EXPORT_BOOK
],
Role.TEACHER: [Permission.ADD_BOOK],
Role.STUDENT: []
}
@classmethod
def has_permission(cls, role, permission):
return permission in cls.ROLE_PERMISSIONS.get(role, [])
設(shè)計亮點:
- 權(quán)限配置集中在一個字典里,清晰直觀。
- 使用
@classmethod,無需實例化即可調(diào)用:PermissionManager.has_permission(...) - 學(xué)生沒有任何權(quán)限,教師只能添加,管理員全有。
六、圖書控制器 ——book_controller.py
from dao.database import Database
from controller.permission_manager import PermissionManager
from model.permission import Permission
class BookController:
def __init__(self, user):
self.db = Database()
self.user = user
def add_book(self, title, author, isbn, category):
if not PermissionManager.has_permission(self.user.role, Permission.ADD_BOOK):
raise Exception("沒有權(quán)限")
self.db.execute("""
INSERT INTO books(title, author, isbn, category)
VALUES (?, ?, ?, ?)
""", (title, author, isbn, category))
def delete_book(self, book_id):
if not PermissionManager.has_permission(self.user.role, Permission.DELETE_BOOK):
raise Exception("沒有權(quán)限")
self.db.execute("DELETE FROM books WHERE id=?", (book_id,))
def list_books(self):
cursor = self.db.execute("SELECT * FROM books")
return cursor.fetchall()
權(quán)限控制集成:
- 每個操作前先檢查權(quán)限,無權(quán)限則拋出異常。
- 異常會被 UI 捕獲并彈窗提示(見后文)。
七、用戶界面(View)
1. 登錄窗口 ——login_window.py
from PyQt5.QtWidgets import *
from controller.user_controller import UserController
from view.register_window import RegisterWindow
class LoginWindow(QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle("登錄")
self.controller = UserController()
# ... 布局代碼 ...
self.user = None
def login(self):
user = self.controller.login(self.edit_user.text(), self.edit_pass.text())
if user:
self.user = user
self.accept() # 關(guān)閉對話框并返回 True
else:
QMessageBox.warning(self, "錯誤", "登錄失敗")
def open_register(self):
RegisterWindow().exec_() # 模態(tài)彈出注冊窗口
要點:
- 繼承
QDialog,適合登錄/注冊這類臨時窗口。 accept()表示“成功關(guān)閉”,main.py中通過if login.exec_():判斷是否登錄成功。- 密碼輸入框設(shè)置為密文:
self.edit_pass.setEchoMode(QLineEdit.Password)
2. 注冊窗口 ——register_window.py
class RegisterWindow(QDialog):
def __init__(self):
super().__init__()
self.combo_role.addItems([Role.TEACHER, Role.STUDENT]) # 只能選教師或?qū)W生
def register(self):
self.controller.register(
self.edit_user.text(),
self.edit_pass.text(),
self.combo_role.currentText()
)
QMessageBox.information(self, "成功", "注冊成功")
self.accept()
限制:普通用戶不能注冊為管理員,防止權(quán)限提升。
3. 不同角色主窗口
學(xué)生窗口 ——student_window.py
- 只有 刷新按鈕
- 沒有添加/刪除按鈕(UI 層就隱藏了)
- 即使通過其他方式調(diào)用
add_book,也會因權(quán)限不足被BookController攔截
教師窗口 ——teacher_window.py
- 有 添加、刪除、刷新 按鈕
- 但刪除時會觸發(fā)權(quán)限檢查 → 教師無
DELETE_BOOK權(quán)限 → 拋出異常 → 彈窗“沒有權(quán)限”
重要:這里存在一個 UI 與權(quán)限不一致 的問題!教師界面上顯示了“刪除”按鈕,但點擊會報錯。更好的做法是:根據(jù)權(quán)限動態(tài)顯示按鈕。
管理員窗口 ——admin_window.py
- 只實現(xiàn)了“添加測試書”功能(硬編碼)
- 實際應(yīng)像教師窗口那樣彈出輸入框(當(dāng)前是簡化版)
八、程序入口 ——main.py
import sys
from PyQt5.QtWidgets import QApplication
from view.login_window import LoginWindow
# ... 導(dǎo)入各角色窗口 ...
if __name__ == "__main__":
app = QApplication(sys.argv)
login = LoginWindow()
if login.exec_(): # 如果登錄成功
user = login.user
if user.role == Role.ADMIN:
window = AdminWindow(user)
elif user.role == Role.TEACHER:
window = TeacherWindow(user)
else:
window = StudentWindow(user)
window.show()
sys.exit(app.exec_())
流程:
- 啟動應(yīng)用
- 彈出登錄窗口
- 登錄成功 → 根據(jù)角色打開對應(yīng)主窗口
- 進入事件循環(huán)
九、潛在問題與改進建議
1. 教師界面顯示了“刪除”按鈕但無權(quán)限
原因:UI 未根據(jù)權(quán)限動態(tài)調(diào)整
修復(fù)建議:
# 在 TeacherWindow.__init__ 中
if PermissionManager.has_permission(user.role, Permission.DELETE_BOOK):
btn_layout.addWidget(self.btn_delete)
2. 管理員窗口功能簡陋
當(dāng)前 add_book 是硬編碼的,應(yīng)改為彈窗輸入。
3. 密碼強度弱
admin 默認密碼 123456 不安全,應(yīng)首次登錄強制修改。
4. 優(yōu)點總結(jié)
- 分層清晰(Model / DAO / Controller / View)
- 權(quán)限控制集中、可擴展
- 使用 SQLite,零配置運行
- 代碼簡潔,適合教學(xué)
十、如何運行
安裝依賴:
pip install PyQt5
將所有 .py 文件放在同一目錄
運行:
python main.py
首次運行會自動創(chuàng)建 library.db 和 admin 賬號
結(jié)語
這個小項目雖然簡單,但涵蓋了:
- 面向?qū)ο缶幊蹋∣OP)
- MVC 架構(gòu)思想
- 數(shù)據(jù)庫操作(SQLite)
- GUI 開發(fā)(PyQt5)
- 權(quán)限控制設(shè)計
- 密碼安全基礎(chǔ)
非常適合 Python 初學(xué)者作為練手項目!你可以在此基礎(chǔ)上:
- 添加“借閱/歸還”功能
- 實現(xiàn)圖書搜索
- 支持 Excel 導(dǎo)入導(dǎo)出(利用已有
IMPORT_BOOK/EXPORT_BOOK權(quán)限)
記住:好的代碼 = 清晰的結(jié)構(gòu) + 明確的職責(zé) + 安全的實踐。
以上就是python結(jié)合QT實現(xiàn)簡單的圖書管理系統(tǒng)的詳細內(nèi)容,更多關(guān)于python圖書管理系統(tǒng)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python借助Free Spire.XLS for Python實現(xiàn)將JSON轉(zhuǎn)換為Ex
將 JSON 數(shù)據(jù)結(jié)構(gòu)化轉(zhuǎn)換為 Excel 文件,是日常開發(fā)中高頻且基礎(chǔ)的需求,本文將介紹如何使用免費庫 Free Spire.XLS for Python 完成這一轉(zhuǎn)換任務(wù),并提供處理復(fù)雜嵌套數(shù)據(jù)的實用方案,希望對大家有所幫助2026-02-02
Python基本類型的連接組合和互相轉(zhuǎn)換方式(13種)
這篇文章主要介紹了Python中基本類型的連接組合和互相轉(zhuǎn)換13種方式,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-12-12
Python結(jié)合Sprak實現(xiàn)計算曲線與X軸上方的面積
這篇文章主要介紹了Python結(jié)合Sprak實現(xiàn)計算曲線與X軸上方的面積,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-02-02

