【实战分享】 从零搭建Python图书管理系统:python+MySQL实现完整业务流程(文末附全部源代码)
今天将基于Python的Tkinter框架(GUI)和MySQL数据库,搭建一个功能完整、界面友好的图书管理系统,实现图书管理、借阅流程、统计分析等核心功能。本文会在原有讲解基础上,嵌入核心代码片段,帮助大家更好地理解和复用。
一、系统整体架构设计
本次搭建的图书管理系统采用分层架构设计,将业务逻辑与界面展示、数据存储解耦,提高代码的可维护性和扩展性,整体架构分为三层:
- 数据层:由
DatabaseManager类负责,处理与MySQL数据库的连接、表结构初始化、SQL执行等底层操作,屏蔽数据库操作的复杂性。 - 业务逻辑层:由
BookManager类负责,封装图书添加、修改、删除、借阅、归还、统计等核心业务逻辑,提供统一的业务接口给上层调用。 - 界面层:由
LibraryApp类负责,基于Tkinter构建可视化GUI界面,处理用户交互事件,调用业务逻辑层接口完成功能展
二、核心技术栈说明
- GUI框架:Tkinter(Python内置,无需额外配置)
- 数据库驱动:PyMySQL(连接MySQL的主流驱动)
- 数据库:MySQL 8.0+(持久化存储数据)
依赖安装代码
pip install pymysql 三、核心功能模块详解(精简核心代码)
(一)数据库管理模块(DatabaseManager)
核心功能:自动创建数据库/表、统一SQL执行、连接管理,精简代码如下:
import pymysql classDatabaseManager:def__init__(self, config): self.config = config self.conn = self._create_connection() self._init_tables()def_create_connection(self):"""自动创建数据库并建立连接"""# 先创建数据库 temp_conn = pymysql.connect(**{ k:v for k,v in self.config.items()if k!='database'})with temp_conn.cursor()as cur: cur.execute(f"CREATE DATABASE IF NOT EXISTS { self.config['database']} DEFAULT CHARSET utf8mb4") temp_conn.close()# 连接目标数据库return pymysql.connect(**self.config)def_init_tables(self):"""初始化图书表和借阅记录表"""with self.conn.cursor()as cur:# 图书表 cur.execute("""CREATE TABLE IF NOT EXISTS books ( id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(200) NOT NULL, author VARCHAR(100) NOT NULL, isbn VARCHAR(20) UNIQUE, stock INT DEFAULT 0, available INT DEFAULT 0 )""")# 借阅记录表 cur.execute("""CREATE TABLE IF NOT EXISTS borrow_records ( id INT AUTO_INCREMENT PRIMARY KEY, book_id INT NOT NULL, borrower_name VARCHAR(50) NOT NULL, FOREIGN KEY (book_id) REFERENCES books(id) )""") self.conn.commit()defexecute(self, sql, params=(), fetch=False):"""统一执行SQL"""with self.conn.cursor()as cur: cur.execute(sql, params)if fetch:return cur.fetchall() self.conn.commit()(二)图书业务管理模块(BookManager)
核心功能:图书增删、借阅归还,精简核心代码如下:

from datetime import datetime, timedelta classBookManager:def__init__(self, db): self.db = db defadd_book(self, title, author, isbn, stock=1):"""添加图书""" sql ="INSERT INTO books (title, author, isbn, stock, available) VALUES (%s,%s,%s,%s,%s)" self.db.execute(sql,(title, author, isbn, stock, stock))defborrow_book(self, book_id, borrower_name):"""借书:校验库存+更新可借数量+生成记录"""# 校验可借数量 book = self.db.execute("SELECT available FROM books WHERE id=%s",(book_id,), fetch=True)ifnot book or book[0][0]<=0:returnFalse# 生成借阅记录 borrow_date = datetime.now().date() return_date = borrow_date + timedelta(days=30) self.db.execute("INSERT INTO borrow_records (book_id, borrower_name, borrow_date, return_date) VALUES (%s,%s,%s,%s)",(book_id, borrower_name, borrow_date, return_date))# 更新可借数量 self.db.execute("UPDATE books SET available = available -1 WHERE id=%s",(book_id,))returnTruedefreturn_book(self, record_id):"""还书:更新状态+恢复可借数量"""# 获取图书ID book_id = self.db.execute("SELECT book_id FROM borrow_records WHERE id=%s",(record_id,), fetch=True)[0][0]# 更新借阅状态 self.db.execute("UPDATE borrow_records SET status='已还', actual_return_date=%s WHERE id=%s",(datetime.now().date(), record_id))# 恢复可借数量 self.db.execute("UPDATE books SET available = available +1 WHERE id=%s",(book_id,))returnTrue(三)GUI界面模块(LibraryApp)
核心功能:搭建三大标签页(图书管理、借阅管理、统计分析),精简核心代码如下:
import tkinter as tk from tkinter import ttk, messagebox classLibraryApp:def__init__(self, root): self.root = root self.root.title("图书管理系统") self.root.geometry("1000x700")# 初始化数据库 self.db_config ={ "host":"localhost","user":"root","password":"root","database":"library_system"} self.db = DatabaseManager(self.db_config) self.book_manager = BookManager(self.db)# 搭建标签页 self.notebook = ttk.Notebook(root) self.notebook.pack(fill="both", expand=True)# 三个核心标签页 ttk.Frame(self.notebook, name="book_frame") ttk.Frame(self.notebook, name="borrow_frame") ttk.Frame(self.notebook, name="stats_frame") self.notebook.add(self.root.nametowidget("book_frame"), text="图书管理") self.notebook.add(self.root.nametowidget("borrow_frame"), text="借阅管理") self.notebook.add(self.root.nametowidget("stats_frame"), text="统计分析")# 图书管理界面(精简版) self._setup_book_ui()def_setup_book_ui(self):"""图书管理界面:搜索+列表+添加按钮""" frame = self.root.nametowidget("book_frame")# 搜索框 tk.Entry(frame, name="search_entry").pack(fill="x", padx=10, pady=5)# 图书列表 tree = ttk.Treeview(frame, columns=("ID","书名","作者"), show="headings") tree.heading("ID", text="ID") tree.heading("书名", text="书名") tree.heading("作者", text="作者") tree.pack(fill="both", expand=True, padx=10, pady=5)# 添加按钮 tk.Button(frame, text="添加图书", command=self._show_add_book).pack(pady=5)def_show_add_book(self):"""显示添加图书弹窗(简易版)"""# 此处省略表单细节,核心是调用book_manager.add_book messagebox.showinfo("提示","打开添加图书表单")主函数(程序启动)
defmain(): root = tk.Tk() LibraryApp(root) root.mainloop()if __name__ =="__main__": main()四、系统核心特性
- 高可用性:自动建库建表,首次启动即可使用
- 数据一致性:借阅/归还自动同步可借数量,避免数据混乱
- 操作友好:界面布局清晰,关键操作有提示
- 可扩展性强:分层架构,便于后续扩展功能
五、系统运行步骤
- 环境准备:安装Python 3.8+、PyMySQL、启动MySQL服务
- 配置修改:修改
db_config中的MySQL密码 - 启动程序:直接运行代码,自动创建数据库和表
- 功能使用:进行图书添加、借阅、归还等操作
本系统基于Python 和MySQL,以精简代码实现了图书管理核心功能,采用分层架构设计,代码简洁易懂、可复用性强。既可以作为Python GUI和数据库操作的实战案例,也可根据实际需求快速二次开发,适用于小型图书馆、图书角等场景。
六、全部实现源代码
- 创建数据库
-- 创建数据库 CREATE DATABASE IF NOT EXISTS library_system CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 使用数据库 USE library_system; 程序会自动创建表结构,无需手动建表
- 修改数据库配置
在代码中修改这部分配置:
self.db_config ={ "host":"localhost",# 数据库主机"user":"root",# 数据库用户名"password":"your_password",# 你的数据库密码,按照自己的MySQL数据用户名和密码填写"database":"library_system",# 数据库名称"port":3306,# 端口号"charset":"utf8mb4",# 字符集}- 全部程序源代码:
import tkinter as tk from tkinter import messagebox, ttk from datetime import datetime, timedelta import pymysql from typing import Dict, List, Optional, Tuple from dataclasses import dataclass import threading @dataclassclassBook:"""图书数据类"""id: Optional[int]=None title:str="" author:str="" isbn:str="" category:str="" publisher:str="" publish_date:str="" price:float=0.0 stock:int=0 available:int=0 status:str="正常"@dataclassclassBorrowRecord:"""借阅记录数据类"""id: Optional[int]=None book_id:int=0 book_title:str="" borrower_name:str="" borrower_phone:str="" borrow_date:str="" return_date:str="" actual_return_date:str="" status:str="借出"classDatabaseManager:"""数据库管理类"""def__init__(self, config: Dict): self.config = config self.conn =None self.ensure_connection() self.init_database()defensure_connection(self)->None:"""确保数据库连接"""try:if self.conn and self.conn.open:try: self.conn.ping(reconnect=False)returnexcept:passexcept:passtry:# 先连接到MySQL,如果数据库不存在则创建 temp_config = self.config.copy() database = temp_config.pop('database')# 先用默认数据库连接,创建目标数据库 temp_config['database']='mysql' temp_conn = pymysql.connect(**temp_config)with temp_conn.cursor()as cursor: cursor.execute(f"CREATE DATABASE IF NOT EXISTS { database} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci") temp_conn.commit() temp_conn.close()# 现在用真实的配置连接 self.config['database']= database self.conn = pymysql.connect(**self.config)print("数据库连接成功")except Exception as e:print(f"数据库连接失败: { e}")raisedefinit_database(self)->None:"""初始化数据库表"""try:with self.conn.cursor()as cursor:# 先删除旧表(可选,用于完全重置)# cursor.execute("DROP TABLE IF EXISTS borrow_records")# cursor.execute("DROP TABLE IF EXISTS books")# cursor.execute("DROP TABLE IF EXISTS categories")# 创建图书表 cursor.execute(""" CREATE TABLE IF NOT EXISTS books ( id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(200) NOT NULL, author VARCHAR(100) NOT NULL, isbn VARCHAR(20) UNIQUE KEY, category VARCHAR(50) NOT NULL, publisher VARCHAR(100), publish_date DATE, price DECIMAL(10,2) DEFAULT 0.00, stock INT DEFAULT 0, available INT DEFAULT 0, status VARCHAR(20) DEFAULT '正常', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_category (category), INDEX idx_status (status) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci """)print("图书表创建成功")# 创建借阅记录表 cursor.execute(""" CREATE TABLE IF NOT EXISTS borrow_records ( id INT AUTO_INCREMENT PRIMARY KEY, book_id INT NOT NULL, borrower_name VARCHAR(50) NOT NULL, borrower_phone VARCHAR(20), borrow_date DATE NOT NULL, return_date DATE NOT NULL, actual_return_date DATE, status VARCHAR(20) DEFAULT '借出', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (book_id) REFERENCES books(id) ON DELETE CASCADE, INDEX idx_book_id (book_id), INDEX idx_status (status), INDEX idx_borrower (borrower_name) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci """)print("借阅记录表创建成功")# 创建图书分类表 cursor.execute(""" CREATE TABLE IF NOT EXISTS categories ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) UNIQUE NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_name (name) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci """)print("分类表创建成功") self.conn.commit() self.init_sample_data()print("数据库表初始化完成")except pymysql.err.ProgrammingError as e:if"already exists"instr(e):print("表已存在,跳过创建") self.init_sample_data()else:print(f"数据库初始化失败: { e}")raiseexcept Exception as e:print(f"数据库初始化失败: { e}")raisedefinit_sample_data(self)->None:"""初始化示例数据"""try:with self.conn.cursor()as cursor:# 检查是否已有数据 cursor.execute("SELECT COUNT(*) FROM books")if cursor.fetchone()[0]>0:print("示例数据已存在,跳过初始化")return# 初始化分类 categories =["计算机科学","文学","历史","哲学","数学","物理","化学","生物","经济学","管理学"]for category in categories:try: cursor.execute("INSERT INTO categories (name) VALUES (%s)",(category,))except pymysql.err.IntegrityError:pass# 分类已存在# 初始化图书数据 books =[("Python编程从入门到实践","埃里克·马瑟斯","9787115428028","计算机科学","人民邮电出版社","2016-07-01",89.00,5),("算法导论","Thomas H. Cormen","9787111407010","计算机科学","机械工业出版社","2012-12-01",128.00,3),("深度学习","Ian Goodfellow","9787115461476","计算机科学","人民邮电出版社","2017-07-01",168.00,2),("JavaScript高级程序设计","Matt Frisbie","9787115583864","计算机科学","人民邮电出版社","2020-09-01",139.00,4),("设计模式","Gang of Four","9787111075776","计算机科学","机械工业出版社","2000-09-01",45.00,3),("红楼梦","曹雪芹","9787020002207","文学","人民文学出版社","1996-12-01",39.50,10),("三国演义","罗贯中","9787020008735"