系统概述
这个图书管理系统是一个命令行界面的应用程序,主要功能包括图书管理、用户管理和借阅管理。系统使用SQLite作为数据库后端,通过面向对象的方式封装了各种操作。
系统设计结构
1. 数据库设计
系统设计了三个主要数据表:
-
books表:存储图书信息
-
id: 主键,自增
-
title: 书名
-
author: 作者
-
isbn: ISBN号(唯一)
-
status: 图书状态(available/borrowed)
-
borrowed_date: 借出日期
-
due_date: 应还日期
-
-
users表:存储用户信息
-
id: 主键,自增
-
name: 用户名
-
email: 邮箱(唯一)
-
password: 密码
-
-
borrow_records表:存储借阅记录
-
id: 主键,自增
-
book_id: 外键关联books表
-
user_id: 外键关联users表
-
borrow_date: 借出日期
-
return_date: 归还日期
-
2. 类设计
系统核心是LibrarySystem
类,封装了所有数据库操作:
class LibrarySystem:
def __init__(self, db_path='library.db'):
# 初始化数据库连接
self.db_path = db_path
self.conn = None
self.cursor = None
self.connect()
self.create_tables()
主要方法分为几类:
-
数据库连接管理
-
connect()
: 建立数据库连接 -
disconnect()
: 关闭数据库连接
-
-
表结构管理
-
create_tables()
: 创建所需的数据库表
-
-
图书管理功能
-
add_book()
: 添加新书 -
remove_book()
: 删除图书 -
search_books()
: 搜索图书 -
list_books()
: 列出所有图书
-
-
用户管理功能
-
register_user()
: 注册新用户 -
authenticate_user()
: 用户认证
-
-
借阅管理功能
-
borrow_book()
: 借阅图书 -
return_book()
: 归还图书 -
list_borrowed_books()
: 列出所有借出的图书
-
代码实现分析
1. 数据库连接与表创建
def create_tables(self):
"""创建必要的表"""
# 创建图书表
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS books (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
author TEXT NOT NULL,
isbn TEXT UNIQUE,
status TEXT NOT NULL DEFAULT 'available',
borrowed_date TEXT,
due_date TEXT
)
''')
-
使用
IF NOT EXISTS
避免重复创建表 -
设置了适当的约束(NOT NULL, UNIQUE等)
-
定义了外键关系确保数据完整性
2. 图书管理实现
添加图书:
def add_book(self, title, author, isbn=None):
try:
self.cursor.execute(
"INSERT INTO books (title, author, isbn) VALUES (?, ?, ?)",
(title, author, isbn)
)
self.conn.commit()
return True, "图书添加成功"
except sqlite3.IntegrityError:
return False, "ISBN已存在"
-
使用参数化查询防止SQL注入
-
捕获
IntegrityError
处理唯一约束冲突 -
返回操作结果和消息
3. 借阅管理实现
借阅图书:
def borrow_book(self, book_id, user_id):
from datetime import datetime, timedelta
try:
# 检查图书是否存在和可借状态
self.cursor.execute("SELECT * FROM books WHERE id = ?", (book_id,))
book = self.cursor.fetchone()
if not book:
return False, "图书不存在"
if book[4] == 'borrowed':
return False, "图书已被借出"
# 更新图书状态
borrow_date = datetime.now().strftime("%Y-%m-%d")
due_date = (datetime.now() + timedelta(days=14)).strftime("%Y-%m-%d")
self.cursor.execute(
"UPDATE books SET status = 'borrowed', borrowed_date = ?, due_date = ? WHERE id = ?",
(borrow_date, due_date, book_id)
)
# 记录借阅信息
self.cursor.execute(
"INSERT INTO borrow_records (book_id, user_id, borrow_date) VALUES (?, ?, ?)",
(book_id, user_id, borrow_date)
)
self.conn.commit()
return True, f"借阅成功,应在 {due_date} 前归还"
-
设置14天的借阅期限
-
同时更新图书状态和创建借阅记录
-
使用事务确保数据一致性
归还图书:
def return_book(self, book_id):
from datetime import datetime
try:
# 检查图书状态
self.cursor.execute("SELECT * FROM books WHERE id = ?", (book_id,))
book = self.cursor.fetchone()
if not book:
return False, "图书不存在"
if book[4] == 'available':
return False, "图书未被借出"
# 更新图书状态
return_date = datetime.now().strftime("%Y-%m-%d")
self.cursor.execute(
"UPDATE books SET status = 'available', borrowed_date = NULL, due_date = NULL WHERE id = ?",
(book_id,)
)
# 更新借阅记录
self.cursor.execute(
"UPDATE borrow_records SET return_date = ? WHERE book_id = ? AND return_date IS NULL",
(return_date, book_id)
)
self.conn.commit()
# 检查逾期情况
due_date = datetime.strptime(book[6], "%Y-%m-%d")
if datetime.now() > due_date:
days_overdue = (datetime.now() - due_date).days
return True, f"归还成功,但已逾期 {days_overdue} 天"
-
处理图书状态更新和借阅记录更新
-
检查并计算逾期天数
-
提供详细的反馈信息
系统特点
-
数据完整性:
-
使用数据库约束(UNIQUE, NOT NULL等)
-
外键关系确保关联数据有效性
-
事务处理保证操作原子性
-
-
安全性:
-
参数化查询防止SQL注入
-
密码存储(虽然示例中为明文,实际应用中应加密)
-
-
用户体验:
-
清晰的错误提示
-
详细的操作反馈
-
简单的命令行界面
-
-
可扩展性:
-
模块化设计便于功能扩展
-
清晰的数据库结构易于修改
-
优化与改进建议
-
密码安全:
-
当前明文存储密码不安全,应使用哈希算法(如bcrypt)加密
-
-
日志记录:
-
添加操作日志功能,记录重要操作
-
-
更复杂的搜索:
-
实现多条件组合搜索
-
添加分页功能
-
-
用户界面:
-
可以开发图形界面或Web界面提升用户体验
-
-
数据备份:
-
添加数据库备份功能
-
完整代码
import sqlite3
import os
class LibrarySystem:
def __init__(self, db_path='library.db'):
self.db_path = db_path
self.conn = None
self.cursor = None
self.connect()
self.create_tables()
def connect(self):
"""连接到数据库"""
self.conn = sqlite3.connect(self.db_path)
self.cursor = self.conn.cursor()
def disconnect(self):
"""断开数据库连接"""
if self.cursor:
self.cursor.close()
if self.conn:
self.conn.close()
def create_tables(self):
"""创建必要的表"""
# 创建图书表
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS books (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
author TEXT NOT NULL,
isbn TEXT UNIQUE,
status TEXT NOT NULL DEFAULT 'available',
borrowed_date TEXT,
due_date TEXT
)
''')
# 创建用户表
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
password TEXT NOT NULL
)
''')
# 创建借阅记录表
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS borrow_records (
id INTEGER PRIMARY KEY AUTOINCREMENT,
book_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
borrow_date TEXT NOT NULL,
return_date TEXT,
FOREIGN KEY (book_id) REFERENCES books (id),
FOREIGN KEY (user_id) REFERENCES users (id)
)
''')
self.conn.commit()
# 图书管理功能
def add_book(self, title, author, isbn=None):
"""添加图书"""
try:
self.cursor.execute(
"INSERT INTO books (title, author, isbn) VALUES (?, ?, ?)",
(title, author, isbn)
)
self.conn.commit()
return True, "图书添加成功"
except sqlite3.IntegrityError:
return False, "ISBN已存在"
except Exception as e:
return False, f"添加图书失败: {str(e)}"
def remove_book(self, book_id):
"""删除图书"""
try:
# 先检查图书是否存在
self.cursor.execute("SELECT * FROM books WHERE id = ?", (book_id,))
if not self.cursor.fetchone():
return False, "图书不存在"
# 检查图书是否被借出
self.cursor.execute("SELECT * FROM books WHERE id = ? AND status = 'borrowed'", (book_id,))
if self.cursor.fetchone():
return False, "图书已被借出,无法删除"
# 删除图书
self.cursor.execute("DELETE FROM books WHERE id = ?", (book_id,))
self.conn.commit()
return True, "图书删除成功"
except Exception as e:
return False, f"删除图书失败: {str(e)}"
def search_books(self, keyword):
"""搜索图书"""
self.cursor.execute(
"SELECT * FROM books WHERE title LIKE ? OR author LIKE ? OR isbn LIKE ?",
(f"%{keyword}%", f"%{keyword}%", f"%{keyword}%")
)
return self.cursor.fetchall()
def list_books(self):
"""列出所有图书"""
self.cursor.execute("SELECT * FROM books")
return self.cursor.fetchall()
# 用户管理功能
def register_user(self, name, email, password):
"""注册用户"""
try:
self.cursor.execute(
"INSERT INTO users (name, email, password) VALUES (?, ?, ?)",
(name, email, password)
)
self.conn.commit()
return True, "用户注册成功"
except sqlite3.IntegrityError:
return False, "邮箱已被注册"
except Exception as e:
return False, f"注册用户失败: {str(e)}"
def authenticate_user(self, email, password):
"""验证用户身份"""
self.cursor.execute(
"SELECT * FROM users WHERE email = ? AND password = ?",
(email, password)
)
return self.cursor.fetchone()
# 借阅管理功能
def borrow_book(self, book_id, user_id):
"""借阅图书"""
from datetime import datetime, timedelta
try:
# 检查图书是否存在
self.cursor.execute("SELECT * FROM books WHERE id = ?", (book_id,))
book = self.cursor.fetchone()
if not book:
return False, "图书不存在"
# 检查图书是否可借
if book[4] == 'borrowed':
return False, "图书已被借出"
# 更新图书状态
borrow_date = datetime.now().strftime("%Y-%m-%d")
due_date = (datetime.now() + timedelta(days=14)).strftime("%Y-%m-%d")
self.cursor.execute(
"UPDATE books SET status = 'borrowed', borrowed_date = ?, due_date = ? WHERE id = ?",
(borrow_date, due_date, book_id)
)
# 记录借阅信息
self.cursor.execute(
"INSERT INTO borrow_records (book_id, user_id, borrow_date) VALUES (?, ?, ?)",
(book_id, user_id, borrow_date)
)
self.conn.commit()
return True, f"借阅成功,应在 {due_date} 前归还"
except Exception as e:
return False, f"借阅失败: {str(e)}"
def return_book(self, book_id):
"""归还图书"""
from datetime import datetime
try:
# 检查图书是否存在
self.cursor.execute("SELECT * FROM books WHERE id = ?", (book_id,))
book = self.cursor.fetchone()
if not book:
return False, "图书不存在"
# 检查图书是否被借出
if book[4] == 'available':
return False, "图书未被借出"
# 更新图书状态
return_date = datetime.now().strftime("%Y-%m-%d")
self.cursor.execute(
"UPDATE books SET status = 'available', borrowed_date = NULL, due_date = NULL WHERE id = ?",
(book_id,)
)
# 更新借阅记录
self.cursor.execute(
"UPDATE borrow_records SET return_date = ? WHERE book_id = ? AND return_date IS NULL",
(return_date, book_id)
)
self.conn.commit()
# 检查是否逾期
due_date = datetime.strptime(book[6], "%Y-%m-%d")
if datetime.now() > due_date:
days_overdue = (datetime.now() - due_date).days
return True, f"归还成功,但已逾期 {days_overdue} 天"
return True, "归还成功"
except Exception as e:
return False, f"归还失败: {str(e)}"
def list_borrowed_books(self):
"""列出所有借出的图书"""
self.cursor.execute("SELECT * FROM books WHERE status = 'borrowed'")
return self.cursor.fetchall()
# 简单的命令行界面
def main():
library = LibrarySystem()
while True:
print("\n===== 图书管理系统 =====")
print("1. 添加图书")
print("2. 删除图书")
print("3. 搜索图书")
print("4. 列出所有图书")
print("5. 注册用户")
print("6. 用户登录")
print("7. 借阅图书")
print("8. 归还图书")
print("9. 查看借出的图书")
print("0. 退出系统")
choice = input("请输入你的选择: ")
if choice == "1":
title = input("请输入书名: ")
author = input("请输入作者: ")
isbn = input("请输入ISBN(可选,直接回车跳过): ") or None
success, message = library.add_book(title, author, isbn)
print(message)
elif choice == "2":
book_id = input("请输入要删除的图书ID: ")
success, message = library.remove_book(int(book_id))
print(message)
elif choice == "3":
keyword = input("请输入搜索关键词: ")
books = library.search_books(keyword)
if books:
for book in books:
print(f"ID: {book[0]}, 书名: {book[1]}, 作者: {book[2]}, ISBN: {book[3]}, 状态: {book[4]}")
else:
print("未找到匹配的图书")
elif choice == "4":
books = library.list_books()
if books:
for book in books:
print(f"ID: {book[0]}, 书名: {book[1]}, 作者: {book[2]}, ISBN: {book[3]}, 状态: {book[4]}")
else:
print("图书馆暂无图书")
elif choice == "5":
name = input("请输入姓名: ")
email = input("请输入邮箱: ")
password = input("请输入密码: ")
success, message = library.register_user(name, email, password)
print(message)
elif choice == "6":
email = input("请输入邮箱: ")
password = input("请输入密码: ")
user = library.authenticate_user(email, password)
if user:
print(f"登录成功,欢迎 {user[1]}!")
current_user_id = user[0]
else:
print("登录失败,邮箱或密码错误")
elif choice == "7":
if 'current_user_id' not in locals():
print("请先登录")
continue
book_id = input("请输入要借阅的图书ID: ")
success, message = library.borrow_book(int(book_id), current_user_id)
print(message)
elif choice == "8":
book_id = input("请输入要归还的图书ID: ")
success, message = library.return_book(int(book_id))
print(message)
elif choice == "9":
books = library.list_borrowed_books()
if books:
for book in books:
print(f"ID: {book[0]}, 书名: {book[1]}, 作者: {book[2]}, 借阅日期: {book[4]}, 应还日期: {book[5]}")
else:
print("暂无借出的图书")
elif choice == "0":
print("感谢使用图书管理系统,再见!")
library.disconnect()
break
else:
print("无效的选择,请重新输入")
if __name__ == "__main__":
main()
总结
这个图书管理系统虽然简单,但涵盖了数据库应用的基本要素,包括数据建模、CRUD操作、事务处理和用户界面。它展示了如何使用Python和SQLite构建一个小型但功能完整的应用程序,适合作为学习数据库编程的示例项目。通过进一步扩展和完善,可以发展为一个实用的图书馆管理工具。