Python简易图书管理系统重构

在本篇课文中,我们将使用Python语言结合MySQL数据库,从零开始构建一个简单的图书管理系统。该系统旨在帮助图书馆管理员轻松管理图书的借阅、归还以及查询图书信息等日常操作。我们将分步介绍需求分析、数据库设计、环境搭建、功能实现等关键环节,并提供详细的源代码示例。

#### **一、需求分析**

图书管理系统的核心功能包括:
- 图书录入:允许管理员添加新书到系统。
- 图书查询:提供按书名、作者、ISBN等关键词查询图书。
- 借阅管理:记录借阅者信息及图书借阅状态。
- 归还管理:更新图书状态为可借阅。
- 数据统计:统计各类图书的借阅次数等。

#### **二、数据库设计**

首先,我们需要设计两个基本表:`books` 和 `borrow_records`。

1. **books** 表结构示例:
 

 - `id` INT PRIMARY KEY AUTO_INCREMENT,- `title` VARCHAR(255) NOT NULL,- `author` VARCHAR(100),- `isbn` VARCHAR(13) UNIQUE,- `status` ENUM('available', 'borrowed') DEFAULT 'available'

2. **borrow_records** 表结构示例:
 

  - `id` INT PRIMARY KEY AUTO_INCREMENT,- `book_id` INT,- `borrower_name` VARCHAR(100),- `borrow_date` DATE,- `return_date` DATE DEFAULT NULL,- FOREIGN KEY (`book_id`) REFERENCES `books`(`id`)

当然,以下是之前设计的图书管理系统中涉及到的MySQL数据库表创建语句。这些语句会创建`users`(用户)、`books`(图书)和`borrow_records`(借阅记录)三个表。请根据实际情况调整数据库用户名、密码以及数据库名称。

```sql


-- 创建 users 表,用于存储系统用户信息
CREATE TABLE IF NOT EXISTS `users` (`id` INT AUTO_INCREMENT PRIMARY KEY,`username` VARCHAR(64) NOT NULL UNIQUE,`password` VARCHAR(128) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- 注意:在实际应用中,应该使用哈希函数处理密码,不要明文存储
-- 示例:`password`字段的值应该是 `hash_function('your-clear-text-password')`-- 创建 books 表,存储图书信息
CREATE TABLE IF NOT EXISTS `books` (`id` INT AUTO_INCREMENT PRIMARY KEY,`title` VARCHAR(255) NOT NULL,`author` VARCHAR(100),`isbn` VARCHAR(13) UNIQUE NOT NULL,`status` ENUM('available', 'borrowed') DEFAULT 'available'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- 创建 borrow_records 表,记录图书的借阅情况
CREATE TABLE IF NOT EXISTS `borrow_records` (`id` INT AUTO_INCREMENT PRIMARY KEY,`book_id` INT,`borrower_name` VARCHAR(100) NOT NULL,`borrow_date` DATE NOT NULL,`return_date` DATE DEFAULT NULL,FOREIGN KEY (`book_id`) REFERENCES `books`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- 确保外键约束在删除书籍记录时级联删除借阅记录

```

请确保在执行这些SQL语句前,你的MySQL服务器已经启动并且你有合适的权限来创建数据库和表。如果使用的是图形化界面的数据库管理工具(如phpMyAdmin或MySQL Workbench),可以直接在对应的界面输入这些SQL命令来创建表。

#### **三、环境搭建**

确保安装了Python和MySQL,以及必要的库:
- 安装`mysql-connector-python`用于Python连接MySQL。
- 安装`prettytable`用于美化输出。

```bash

pip install mysql-connector-python prettytable


```

#### **四、功能实现**

接下来,我们逐步实现上述功能。

##### 1. 连接数据库```python

import mysql.connector
from prettytable import PrettyTabledef create_conn():conn = mysql.connector.connect(host='localhost',user='your_username',password='your_password',database='library_db')return conndef close_conn(conn):if conn.is_connected():conn.close()


```

##### 2. 图书录入

```python

def add_book(title, author, isbn):conn = create_conn()cursor = conn.cursor()query = "INSERT INTO books (title, author, isbn) VALUES (%s, %s, %s)"try:cursor.execute(query, (title, author, isbn))conn.commit()print("图书添加成功!")except mysql.connector.Error as err:print(f"错误:{err}")finally:close_conn(conn)


```

##### 3. 图书查询

```python

def search_books(keyword):conn = create_conn()cursor = conn.cursor()query = "SELECT * FROM books WHERE title LIKE %s OR author LIKE %s"pattern = f"%{keyword}%"cursor.execute(query, (pattern, pattern))rows = cursor.fetchall()if rows:table = PrettyTable(["ID", "书名", "作者", "ISBN", "状态"])for row in rows:table.add_row(row)print(table)else:print("未找到相关图书。")close_conn(conn)


```

##### 4. 借阅图书

```python

def borrow_book(book_id, borrower_name):conn = create_conn()cursor = conn.cursor()# 检查图书是否可借check_query = "SELECT status FROM books WHERE id = %s AND status = 'available'"cursor.execute(check_query, (book_id,))result = cursor.fetchone()if result:update_query = "UPDATE books SET status = 'borrowed' WHERE id = %s"insert_query = "INSERT INTO borrow_records (book_id, borrower_name, borrow_date) VALUES (%s, %s, CURDATE())"cursor.execute(update_query, (book_id,))cursor.execute(insert_query, (book_id, borrower_name))conn.commit()print("图书借阅成功!")else:print("该图书不可借阅。")close_conn(conn)


```

##### 5. 归还图书

```python

def return_book(book_id):conn = create_conn()cursor = conn.cursor()# 更新图书状态update_query = "UPDATE books SET status = 'available' WHERE id = %s"cursor.execute(update_query, (book_id,))# 更新归还日期update_return_date = "UPDATE borrow_records SET return_date = CURDATE() WHERE book_id = %s AND return_date IS NULL"cursor.execute(update_return_date, (book_id,))conn.commit()if cursor.rowcount > 0:print("图书归还成功!")else:print("该图书未借出或已归还。")close_conn(conn)


```

#### **五、运行示例**

在实际使用中,可以根据需要调用上述函数来完成相应的图书管理任务。例如,要添加一本新书,可以这样操作:

```python

add_book("Python编程入门", "John Doe", "978-3-16-148410-0")


```

通过以上步骤,我们已经构建了一个基本的图书管理系统。当然,实际应用中还需要考虑更多细节,比如异常处理、用户界面、权限管理等,但本教程为你提供了实现此类系统的基本框架和思路。希望这个示例能激发你进一步探索Python与数据库应用开发的兴趣。

页面展示:

### **环境准备**

确保已安装以下依赖:
- Flask
- Flask-Login(用于权限管理)
- Flask-WTF(表单处理)
- Flask-SQLAlchemy(简化SQLAlchemy与Flask的集成)
- Bootstrap(前端样式框架)

```bash

pip install flask flask-login flask-wtf flask-sqlalchemy


```

### **项目结构**

```plaintext
book_management/

├── app.py
├── templates/
│   ├── base.html
│   ├── login.html
│   ├── dashboard.html
│   └── ...
├── static/
│   ├── css/
│   │   └── style.css
│   └── js/
│       └── script.js
├── models.py
└── forms.py
```

### **核心代码示例**

#### **app.py** - 应用入口```python

from flask import Flask, render_template, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user
from models import db, User, Books, BorrowRecords, login
from forms import LoginForm, AddBookFormapp = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:password@localhost/library_db'
db.init_app(app)
login.init_app(app)
login.login_view = 'login'@app.route('/')
@login_required
def dashboard():form = AddBookForm()books = Books.query.all()return render_template('dashboard.html', books=books, form=form)@app.route('/login', methods=['GET', 'POST'])
def login():form = LoginForm()if form.validate_on_submit():user = User.query.filter_by(username=form.username.data).first()if user and user.password == form.password.data:login_user(user)return redirect(url_for('dashboard'))else:form.password.errors.append('Invalid username or password.')return render_template('login.html', form=form)@app.route('/logout')
@login_required
def logout():logout_user()return redirect(url_for('login'))@app.route('/add_book', methods=['POST'])
@login_required
def add_book():form = AddBookForm()if form.validate_on_submit():new_book = Books(title=form.title.data, author=form.author.data, isbn=form.isbn.data)db.session.add(new_book)db.session.commit()return redirect(url_for('dashboard'))return redirect(url_for('dashboard'))if __name__ == '__main__':app.run(debug=True)


```

#### **models.py** - 数据模型定义```python

from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hashdb = SQLAlchemy()class User(UserMixin, db.Model):id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(64), unique=True, nullable=False)password = db.Column(db.String(128), nullable=False)class Books(db.Model):id = db.Column(db.Integer, primary_key=True)title = db.Column(db.String(255), nullable=False)author = db.Column(db.String(100))isbn = db.Column(db.String(13), unique=True, nullable=False)status = db.Column(db.Enum('available', 'borrowed'), default='available')# 注意:省略了BorrowRecords模型以简化示例


```

#### **forms.py** - 表单定义```python

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Length, ValidationErrorclass LoginForm(FlaskForm):username = StringField('Username', validators=[DataRequired()])password = PasswordField('Password', validators=[DataRequired()])submit = SubmitField('Log In')class AddBookForm(FlaskForm):title = StringField('Title', validators=[DataRequired()])author = StringField('Author')isbn = StringField('ISBN', validators=[DataRequired(), Length(min=13, max=13)])submit = SubmitField('Add Book')


```

#### **前端模板** - 使用Bootstrap美化

在`templates/dashboard.html`中,你可以使用Bootstrap框架来美化你的网页布局和样式。例如,为图书列表添加表格样式,以及使用Bootstrap表单组件来美化添加图书的表单。

当然,下面是一个简化的`templates/dashboard.html`示例,展示了如何使用Bootstrap来美化图书管理系统的前端界面。此模板包括一个登录后的仪表板页面,其中包含图书列表和一个添加新书的表单。```html
<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}"><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous"><title>图书管理系统</title>
</head>
<body><nav class="navbar navbar-expand-lg navbar-light bg-light"><a class="navbar-brand" href="#">图书管理系统</a><button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="navbarNav"><ul class="navbar-nav ml-auto"><li class="nav-item"><a class="nav-link" href="{{ url_for('logout') }}">登出</a></li></ul></div>
</nav><div class="container mt-3"><h2>图书列表</h2><table class="table table-striped"><thead><tr><th scope="col">#</th><th scope="col">书名</th><th scope="col">作者</th><th scope="col">ISBN</th><th scope="col">状态</th></tr></thead><tbody>{% for book in books %}<tr><td>{{ book.id }}</td><td>{{ book.title }}</td><td>{{ book.author }}</td><td>{{ book.isbn }}</td><td>{{ book.status }}</td></tr>{% endfor %}</tbody></table><h2>添加新书</h2><form method="post" action="{{ url_for('add_book') }}" class="mt-4">{{ form.hidden_tag() }}<div class="form-group">{{ form.title.label(class="form-control-label") }}{{ form.title(class="form-control") }}</div><div class="form-group">{{ form.author.label(class="form-control-label") }}{{ form.author(class="form-control") }}</div><div class="form-group">{{ form.isbn.label(class="form-control-label") }}{{ form.isbn(class="form-control") }}</div><button type="submit" class="btn btn-primary">添加图书</button></form>
</div><script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p"crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV"crossorigin="anonymous"></script>
</body>
</html>
```

此模板利用了Bootstrap的CSS和JS文件,以及jQuery和Popper.js(Bootstrap的一些JavaScript插件依赖它们)。请注意,你需要确保在你的`static/css`目录下有一个`style.css`文件,用于存放自定义的CSS样式。此外,Flask的`url_for`函数被用来正确地链接静态资源和路由。

### **总结**

通过上述重构,我们的图书管理系统不仅增加了异常处理和用户界面,还引入了基本的权限管理机制,并通过Bootstrap对网页进行了美化。这使得系统更加易用且具有一定的安全防护能力,适合小型图书馆或个人项目使用。请记得根据实际情况调整数据库配置、密钥等敏感信息,并根据需要进一步完善功能和优化前端设计。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/13285.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

注册讲堂 | 体外诊断试剂分类目录的变化

5月11日&#xff0c;千呼万唤的《体外诊断试剂分类目录》&#xff08;2024年第58号&#xff09;终于发布&#xff01; 前世今生 2013年&#xff1a;《6840 体外诊断试剂分类子目录&#xff08;2013版&#xff09;》&#xff08;以下简称2013版目录&#xff09; 2017年&#xff…

苹果永久版安装PD虚拟机:Parallels Desktop 19 一键激活版

Parallels Desktop 19是一款功能强大的虚拟机软件&#xff0c;专为Mac用户设计&#xff0c;允许用户在同一台Mac电脑上同时运行Windows、Linux等多个操作系统&#xff0c;而无需额外的硬件设备。 下载地址&#xff1a;https://www.macz.com/mac/9581.html?idOTI2NjQ5Jl8mMjcuM…

Kubernetes入门:核心概念

集群架构与组件 一个kubernetes集群主要是由控制节点(master)、工作节点(node)构成&#xff0c;每个节点上都会安装不同的组件。 master&#xff1a;集群的控制平面&#xff0c;负责集群的决策 ( 管理 ) api-server : 资源操作的唯一入口&#xff0c;接收用户输入的命令&…

vue3 项目中 前端实现下载模板 csv文件

做项目时遇到让前端实现模板下载功能&#xff0c;第一次碰到这种需求&#xff0c;记录一下。 下载csv 模板&#xff1a; <el-button type"primary" click"download(data/CSVXX.csv)">下载模板</el-button> const download (url) > {con…

文本控件Text Control示例: 将图像插入 TX 的各种方法

TX Text Control 是一款功能类似于 MS Word 的文字处理控件&#xff0c;包括文档创建、编辑、打印、邮件合并、格式转换、拆分合并、导入导出、批量生成等功能。广泛应用于企业文档管理&#xff0c;网站内容发布&#xff0c;电子病历中病案模板创建、病历书写、修改历史、连续打…

在Linux上面部署ELK

注明&#xff1a;一下的软件需要自己准备 一、准备环境&#xff1a; 1.两台elasticsearch主机4G内存 2.两台elasticsearch配置主机名node1和node2(可以省略) #vim /etc/hostname #reboot 3. 两台elasticsearch配置hosts文件 #vim /etc/hosts 192.168.1.1 node1 192…

RTMP低延迟推流

人总是需要压力才能进步, 最近有个项目, 需要我在RK3568上, 推流到公网, 最大程度的降低延迟. 废话不多说, 先直接看效果: 数据经过WiFi发送到Inenter的SRS服务器, 再通过网页拉流的. 因为是打金任务, 所以逼了自己一把, 把RTMP推流好好捋一遍. 先说说任务目标, 首先是MPP编码…

【Altium】AD-检查原理图中元器件未连接的Passive Pin

1、 文档目标 如何让原理图编译时找出元器件上未连接的Passive Pin 2、 问题场景 当引脚属性&#xff08;Pin type&#xff09;为passive时&#xff0c;原理图编译的默认规则是不会去检查它们是否有连接的。在实际设计过程中&#xff0c;经常会有导线虚连&#xff0c;漏连的事…

医疗传感器种类不断增多 市场规模逐渐扩大

医疗传感器种类不断增多 市场规模逐渐扩大 医疗传感器是将人体的生理信息转换为电信息的变换装置。医疗传感器具有高灵敏度、高精度、实时监测等优点&#xff0c;可以检测佩戴者的心率、呼吸频率、活动量等&#xff0c;从而更加准确地了解身体情况。   经过多年发展&#…

【极简】docker常用操作

镜像images是静态的 容器container是动态的&#xff0c;是基于镜像的&#xff0c;类似于一个进程。 查看docker images&#xff1a; docker images 或者docker image ls 查看docker container情况&#xff1a;docker ps -a&#xff0c;-a意思是--all 运行一个container: doc…

MySQL not in不等于找不到null的数据

在使用MySQL的NOT IN语句时&#xff0c;如果找不到NULL值&#xff0c;可能是因为NULL值在比较中具有特殊性质。NULL值不等于任何其他值&#xff0c;包括它自己。因此&#xff0c;使用NOT IN语句时&#xff0c;如果列表中包含NULL值&#xff0c;则查询不会返回任何结果。 解决此…

有意思的数组

var nums [1,2,3,6] const nums1 [6, 8, 7, 10, 9];/* 数组合并————push */ var n nums.push(...nums1); // 将列表 nums1 拼接到 nums 之后 n //n会是nums的长度 > 9 nums //也push了 > (9) [1, 2, 3, 6, 6, 8, 7, 10, 9]/* 数组合并————concat*/ var arr0…

数字水印 | 奇异值分解 SVD 的 Python 代码实现

&#x1f951;原理&#xff1a;数字水印 | 奇异值分解 SVD 的定义、原理及性质 &#x1f951;参考&#xff1a;Python 机器学习笔记&#xff1a;奇异值分解&#xff08;SVD&#xff09;算法 正文 对于一个图像矩阵&#xff0c;我们总可以将其分解为以下形式&#xff1a; 通过…

使用API有效率地管理Dynadot域名,默认将域名隐形转发至其他界面

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…

英译汉早操练-(十九)

hello,are you OK? 生活如此美好&#xff0c;周四了&#xff0c;你还好吗&#xff1f;坚持了快一周了&#xff0c;是不是最后冲刺一把就开启周末的美好生活了。 今天我们学习这篇经济学人文章&#xff1a; 题目是&#xff1a;Banks, at least, are making money from a turbul…

【大模型微调】一文掌握7种大模型微调的方法

本篇文章深入分析了大型模型微调的基本理念和多样化技术&#xff0c;细致介绍了LoRA、适配器调整(Adapter Tuning)、前缀调整(Prefix Tuning)等多个微调方法。详细讨论了每一种策略的基本原则、主要优点以及适宜应用场景&#xff0c;使得读者可以依据特定的应用要求和计算资源限…

Linux | VMware安装镜像指南(Windows、IOS、麒麟)

文章目录 虚拟机安装推荐 虚拟机安装推荐 macOS系统&#xff1a;macOS虚拟机安装全过程&#xff08;VMware&#xff09;麒麟系统&#xff1a;麒麟系统虚拟机安装&#xff08;VMware&#xff09;VMtools工具解决方案&#xff1a; [第一步](https://blog.csdn.net/weixin_421187…

openGauss一主两备集群异常断电后不能正常启动的解决过程简记

背景 因异常断电后opengauss 5.0.0版本&#xff0c;一主两备集群启动失败。 报错不是主机&#xff0c;由于当时没有截图&#xff0c;查看日志后发现报错是&#xff1a; 定位过程 Day1 1. 尝试用另外两台机器启动每台机器 发现都报错自己不是主机&#xff0c;像极了唐僧被妖…

【算法刷题day55】Leetcode:583. 两个字符串的删除操作、72. 编辑距离

文章目录 Leetcode 583. 两个字符串的删除操作解题思路代码总结 Leetcode 72. 编辑距离解题思路代码总结 草稿图网站 java的Deque Leetcode 583. 两个字符串的删除操作 题目&#xff1a;583. 两个字符串的删除操作 解析&#xff1a;代码随想录解析 解题思路 dp数组的含义是&a…