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 PrettyTable

def create_conn():
    conn = mysql.connector.connect(
        host='localhost',
        user='your_username',
        password='your_password',
        database='library_db'
    )
    return conn

def 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, AddBookForm

app = 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_hash

db = 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, ValidationError

class 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对网页进行了美化。这使得系统更加易用且具有一定的安全防护能力,适合小型图书馆或个人项目使用。请记得根据实际情况调整数据库配置、密钥等敏感信息,并根据需要进一步完善功能和优化前端设计。

  • 30
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值