图书管理系统(python、django)
作者:mmseoamin日期:2023-12-05

1. 系统简介

该实验设计开发一个简单的图书管理数据库系统,包括图书馆内书籍的信息、学校在校师生的信息以及师生的借阅信息。此系统用户面向图书管理员和借阅读者,图书馆管理员可以完成图书、读者等基本信息的增加、删除和修改、查看;读者可以进行图书的借阅、查看、预约等操作。构建基于B/S架构,MySQL数据库为基础,应用Django框架建设过程和方法。本系统主要包含以下基本功能,主要是前台展示和后台管理两部分,其中前台展示包括登陆模块、首页展示、书籍检索、分类查看等。

系统开发技术及工具:Python  Django  HTML  MySQL数据库 Windows11系统  PyCharm

  1. 2.系统分析
  2. 2.1 功能简介:
  3. 图书管理系统(python、django),第1张

 

2.2 功能需求描述

借阅功能:

图书出借时考虑的问题:

读者是否因为超期、罚款等情况被关闭了借阅权限;

读者是否已经借满其限额。

该书是否不在库中;

如果不存在以上情况,则可以出借。

预约功能:

读者想借的书如果不在库中(已经被出借),读者可以预约该图书

读者管理功能:

对读者信息进行查看、添加、修改、删除。将读者分为不同类别,赋以不同权限。

系统管理功能:

对管理员的登录账号、密码进行添加、修改、删除。

违规管理功能:

对违规信息进行查看、添加、修改、删除。

3系统数据库设计

3.1系统概念模型设计

数据库需要描述的数据信息包括以下几种:

(1)读者信息

(2)书籍信息

(3)管理员信息

(4)读者与书籍之间的关系(借阅关系E-R图)

3.2数据库的详细设计

3.2.1数据表的详细设计

图书管理系统由三个实体:图书实体,读者实体,管理员实体,图书种类实体组成,共六个表如下:

1、书籍表

属性:图书编号,ISBN,书名,作者,出版社,出版日期,价格,学科类型,藏书类型,总量,余量

主键:图书编号

2、读者表

属性:读者编号,读者姓名,联系电话,邮箱地址,所在系,权限状况

主键:读者编号

3、管理员用户表

属性:编号,账号,密码,姓名

4、借阅表

属性:图书编号,读者编号,借阅日期,应还日期

5、预约信息

属性:编号,图书编号,读者编号,预约日期

6、违规表

属性:编号,读者编号,图书编号,逾期(0/1),破坏书籍(0/1)

3.2.2 E-R图

1、图书实体E-R图

图书具有图书编号,ISBN,书名,作者,出版社,出版日期,价格,总量,余量等九个属性,便于读者在使用图书馆管理系统时,更加准确的定位到所选图书的位置,了解图书的信息。也可以方便读者利用碎片化的信息,从大量的图书中筛选自己可能心仪图书。

图书管理系统(python、django),第2张

 

2、图书馆管理员实体E-R图

图书管理员实体具有编号,账号,密码,姓名,联系方式

图书管理系统(python、django),第3张

3、读者实体E-R图

读者具有读者编号,读者姓名,联系电话,邮箱地址,备注,便于图书管理员及时的维护管理借阅系统,明确每一本图书的去向,对与图书馆图书的情况有一个把握。维护图书管理系统的正常运行。

图书管理系统(python、django),第4张

4、总体E-R图

在图书管理系统中,一名读者可以借阅多本图书,多名图书管理员同时管理多本图书,一名读书管理员可以同时管理多名读者。通过实体之间的相互联系,构成了图书管理系统的总体E-R图。

图书管理系统(python、django),第5张

3.3表设计

1、读者表(reader)

列名

类型

长度

约束

备注

id

int

主键

编号

reader_id

int

11

学号

password

char

20

密码

name

char

10

读者姓名

telephone

char

15

联系电话

email

char

30

邮箱地址

dept

char

20

所在院系

right

int

1

借阅权限(0或1)

2、图书表(book)

列名

类型

长度

约束

备注

id

int

主键

编号

bookname

char

20

书籍名称

author

char

20

书籍作者

pubdate

date

出版日期

publish

char

30

出版社

price

decimal

7,2

非空

价格

ISBN

char

17

非空

书籍ISBN码

bookclass

int

11

外键

学科类型

total

int

非空

总量

margin

int

非空

余量

booktype

int

11

外键

藏书类型

  1. 管理员用户表(admin)

列名

类型

长度

约束

备注

id

Int

主键

  1. 管理员编号

usernum

Char

20

  1. 管理员账号

password

Char

11

  1. 账号密码

username

char

10

管理员姓名

4.借阅表(borrow)

列名

类型

长度

约束

备注

id

int

主键

借阅编号

readerid

int

读者编号

bookid

int

图书编号

borrowdate

date

出借日期

due

date

应还日期

5.预约表(preconcert)

列名

类型

长度

约束

备注

id

int

主键

预约编号

readerid

int

读者编号

bookid

int

图书编号

predate

date

预约日期

6.违规表(break_rule)

列名

类型

长度

约束

备注

id

int

主键

违规编号

reader_id

int

读者编号

book_id

int

图书编号

verdue

int

逾期(0或1)

destory

int

破坏书籍(0或1)

3配置环境

3.1安装和配置环境

3.3表设计

1、读者表(reader)

列名

类型

长度

约束

备注

id

int

主键

编号

reader_id

int

11

学号

password

char

20

密码

name

char

10

读者姓名

telephone

char

15

联系电话

email

char

30

邮箱地址

dept

char

20

所在院系

right

int

1

借阅权限(0或1)

2、图书表(book)

列名

类型

长度

约束

备注

id

int

主键

编号

bookname

char

20

书籍名称

author

char

20

书籍作者

pubdate

date

出版日期

publish

char

30

出版社

price

decimal

7,2

非空

价格

ISBN

char

17

非空

书籍ISBN码

bookclass

int

11

外键

学科类型

total

int

非空

总量

margin

int

非空

余量

booktype

int

11

外键

藏书类型

  1. 管理员用户表(admin)

列名

类型

长度

约束

备注

id

Int

主键

  1. 管理员编号

usernum

Char

20

  1. 管理员账号

password

Char

11

  1. 账号密码

username

char

10

管理员姓名

4.借阅表(borrow)

列名

类型

长度

约束

备注

id

int

主键

借阅编号

readerid

int

读者编号

bookid

int

图书编号

borrowdate

date

出借日期

due

date

应还日期

5.预约表(preconcert)

列名

类型

长度

约束

备注

id

int

主键

预约编号

readerid

int

读者编号

bookid

int

图书编号

predate

date

预约日期

6.违规表(break_rule)

列名

类型

长度

约束

备注

id

int

主键

违规编号

reader_id

int

读者编号

book_id

int

图书编号

verdue

int

逾期(0或1)

destory

int

破坏书籍(0或1)

3配置环境

3.1安装和配置环境

3.3表设计

1、读者表(reader)

列名

类型

长度

约束

备注

id

int

主键

编号

reader_id

int

11

学号

password

char

20

密码

name

char

10

读者姓名

telephone

char

15

联系电话

email

char

30

邮箱地址

dept

char

20

所在院系

right

int

1

借阅权限(0或1)

2、图书表(book)

列名

类型

长度

约束

备注

id

int

主键

编号

bookname

char

20

书籍名称

author

char

20

书籍作者

pubdate

date

出版日期

publish

char

30

出版社

price

decimal

7,2

非空

价格

ISBN

char

17

非空

书籍ISBN码

bookclass

int

11

外键

学科类型

total

int

非空

总量

margin

int

非空

余量

booktype

int

11

外键

藏书类型

  1. 管理员用户表(admin)

列名

类型

长度

约束

备注

id

Int

主键

  1. 管理员编号

usernum

Char

20

  1. 管理员账号

password

Char

11

  1. 账号密码

username

char

10

管理员姓名

4.借阅表(borrow)

列名

类型

长度

约束

备注

id

int

主键

借阅编号

readerid

int

读者编号

bookid

int

图书编号

borrowdate

date

出借日期

due

date

应还日期

5.预约表(preconcert)

列名

类型

长度

约束

备注

id

int

主键

预约编号

readerid

int

读者编号

bookid

int

图书编号

predate

date

预约日期

6.违规表(break_rule)

列名

类型

长度

约束

备注

id

int

主键

违规编号

reader_id

int

读者编号

book_id

int

图书编号

verdue

int

逾期(0或1)

destory

int

破坏书籍(0或1)

3配置环境

3.1安装和配置环境

选择Pycharm工具进行本次项目的制作

  1. 创建django项目

图书管理系统(python、django),第6张

 

目录说明:

manage.py:一个命令行工具,可以说Django项目就是从这个文件开始执行的。

_init _.py:一个空文件,表示mytest应该被看做一个python包;

settings.py:整个项目的配置参数文件;

urls.py:项目的URL声明,一般项目的顶级url正则匹配放置在这里;

wsgi.py:项目与WSGI兼容的Web服务器入口;

2.创建应用

(1)项目创建完成后需要有具体的应用

图书管理系统(python、django),第7张

 

(2)创建后生成目录:

admin.py: 模型注册和后台管理相关的文件;

_init_.py: 应用应该被看做一个Python包;

migrations: 用来放置应用模型的迁移脚本文件;

models.py: 定义模型;

test.py: 放置项目的测试文件;

viems.py: 定义视图;

图书管理系统(python、django),第8张

 

(3)添加应用

打开settings.py,INSTALLED_APPS下添加:'app01'

3.2配置数据库

在settings.py下:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'BookSystem',
        'USER':'root',
        'PASSWORD':'root',
        'HOST':'localhost',
        'POST':3306,
    }
}

另外django连接mysql需要pymysql包的支持,所以先安装pymysql:

在终端:pip install pymysql

安装完毕,需要导入到django中,打开应用_init_.py文件,加入代码:

import pymysql

pymysql.install_as_MySQLdb()  # 与mysql交互的函数

3.3配置模板和静态文件

 图书管理系统(python、django),第9张

图书管理系统(python、django),第10张 

 4.相关代码展示

4.1. urls层

#读者
    path("reader/search/", views.reader_search),
    path("reader/classify/", views.reader_classify2),
    path("reader//classify/", views.reader_classify),
    path("reader/order/", views.reader_order),
    path("reader/borrow/",views.reader_borrow),
    path("reader/first/", views.reader_first),
    path("reader/rule/", views.reader_rule),
    path("popular/book/", views.popular_book),
    #管理员
    #图书管理
    path("book/list/",views.book_list),
    path("book/add/",views.book_add),
    path("book//edit/",views.book_edit),
    path("book//delete/", views.book_delete),
    #用户管理
    path("user/list/", views.user_list),
    path("user/add/",views.user_add),
    path("user//edit/",views.user_edit),
    path("user//delete/", views.user_delete),
    #管理管理员
    path("admin/list/", views.admin_list),
    path("admin/add/",views.admin_add),
    path("admin//edit/",views.admin_edit),
    path("admin//delete/", views.admin_delete),
    #违规
    path("rule/list/", views.rule_list),
    path("rule/add/",views.rule_add),
    path("rule//edit/",views.rule_edit),
    path("rule//delete/", views.rule_delete),
    #登录
    path("login/",views.login),
    path("log/", views.log)

4.2.models层

class reader(models.Model):
    """"读者表"""
    reader_id=models.IntegerField(verbose_name="学号")
    password=models.CharField(verbose_name="密码",max_length=20)
    name=models.CharField(verbose_name="读者姓名",max_length=10)
    telephone=models.CharField(verbose_name="联系电话",max_length=15)
    email=models.CharField(verbose_name="邮箱地址",max_length=30)
    dept=models.CharField(verbose_name="所在院系",max_length=20)
    right=models.IntegerField(verbose_name="借阅权限(0或1)")
class book(models.Model):
    """"图书表"""
    bookname=models.CharField(verbose_name="书籍名称",max_length=20)
    author=models.CharField(verbose_name="书籍作者",max_length=20)
    pubdate=models.DateField(verbose_name="出版日期")
    publish=models.CharField(verbose_name="出版社",max_length=30)
    price = models.DecimalField(verbose_name="价格", max_digits=7, decimal_places=2, default=0)
    ISBN=models.CharField(verbose_name="书籍ISBN码",max_length=17)
    bookclass_choices=(
        (1,"哲学、宗教"),
        (2,"社会科学总论"),
        (3,"政治、法律"),
        (4,"军事"),
        (5,"经济"),
    )
    bookclass=models.IntegerField(verbose_name="学科类型",choices=bookclass_choices)
    total=models.IntegerField(verbose_name="总量")
    margin=models.IntegerField(verbose_name="余量")
    booktype_choices=(
        (1,"图书"),
        (2,"期刊")
    )
    booktype=models.IntegerField(verbose_name="藏书类型",choices=booktype_choices)
class admin(models.Model):
    """"管理员用户表"""
    usernum=models.CharField(verbose_name="管理员账号",max_length=20)
    password=models.CharField(verbose_name="账号密码",max_length=11)
    username=models.CharField(verbose_name="管理员姓名",max_length=10)
class borrow(models.Model):
    """"借阅表"""
    readerid=models.IntegerField(verbose_name="读者编号")
    bookid=models.IntegerField(verbose_name="图书编号")
    borrowdate=models.DateField(verbose_name="出借日期")
    due=models.DateField(verbose_name="应还日期")
class preconcert(models.Model):
    """"预约表"""
    readerid = models.IntegerField(verbose_name="读者编号")
    bookid = models.IntegerField(verbose_name="图书编号")
    predate = models.DateField(verbose_name="预约日期")
class break_rule(models.Model):
    """"违规表"""
    readerid=models.IntegerField(verbose_name="读者编号")
    bookid=models.IntegerField(verbose_name="图书编号")
    overdue_choices = (
        (0, "无"),
        (1, "逾期")
    )
    overdue=models.IntegerField(verbose_name="逾期(0/1)",choices=overdue_choices)
    destory_choices = (
        (0, "无"),
        (1, "损坏")
    )
    destory=models.IntegerField(verbose_name="破坏书籍(0/1)",choices=destory_choices)

4.3.views层

# ###############################管理员###################################
#管理图书
def book_list(request):
    b = models.book.objects.all()
    return render(request, 'book_list.html', {'b': b})
class BookAdd(forms.ModelForm):
    class Meta:
        model=models.book
        fields=["bookname","author","pubdate","publish","ISBN","price","bookclass","total","margin","booktype"]
        # widgets={
        #     "bookname":forms.TextInput(attrs={"class":"form-control"})
        # }
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环找到所有的插件,添加class=“form——control”
        for name, field in self.fields.items():
           # if name=="password":
            #    continue
            field.widget.attrs = {"class": "form-control"}
def book_add(request):
    if request.method == "GET":
        bookadd = BookAdd()
        return render(request, 'book_add.html', {'bookadd': bookadd})
    #用户POST提交数据,数据校验
    bookadd=BookAdd(data=request.POST)
    if bookadd.is_valid():
        #如果数据合法,保存到数据库
        bookadd.save()
        return redirect('/book/list/')
    #校验失败
    return render(request, 'book_add.html', {'bookadd': bookadd})
def book_edit(request,nid):
    """"编辑书籍"""
    row_object = models.book.objects.filter(id=nid).first()
    if request.method == "GET":
        # 根据id去数据库获取要编辑的那一行数据
        bookadd = BookAdd(instance=row_object)
        return render(request, "book_edit.html", {'bookadd': bookadd})
    bookadd=BookAdd(data=request.POST,instance=row_object)
    if bookadd.is_valid():
        # 如果数据合法,保存到数据库
        bookadd.save()
        return redirect('/book/list/')
    return render(request, "book_edit.html", {'bookadd': bookadd})
def book_delete(request,nid):
    """"删除图书"""
    models.book.objects.filter(id=nid).delete()
    return redirect('/book/list/')
#管理用户
def user_list(request):
    b = models.reader.objects.all()
    return render(request, 'user_list.html', {'b': b})
class User(forms.ModelForm):
    class Meta:
        model=models.reader
        fields=["reader_id","password","name","telephone","email","dept","right"]
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环找到所有的插件,添加class=“form——control”
        for name, field in self.fields.items():
           # if name=="password":
            #    continue
            field.widget.attrs = {"class": "form-control"}
def user_add(request):
    if request.method == "GET":
       user=User()
       return render(request, 'user_add.html', {'user': user})
    #用户POST提交数据,数据校验
    user=User(data=request.POST)
    if user.is_valid():
        #如果数据合法,保存到数据库
        user.save()
        return redirect('/user/list/')
    #校验失败
    return render(request, 'user_add.html', {'user': user})
def user_edit(request,nid):
    """"编辑用户"""
    row_object = models.reader.objects.filter(id=nid).first()
    if request.method == "GET":
        # 根据id去数据库获取要编辑的那一行数据
        user = User(instance=row_object)
        return render(request, "user_edit.html", {'user': user})
    user=User(data=request.POST,instance=row_object)
    if user.is_valid():
        # 如果数据合法,保存到数据库
        user.save()
        return redirect('/user/list/')
    return render(request, "user_edit.html", {'user': user})
def user_delete(request,nid):
    """"删除用户"""
    models.reader.objects.filter(id=nid).delete()
    return redirect('/user/list/')
#管理管理员
def admin_list(request):
    b = models.admin.objects.all()
    return render(request, 'admin_list.html', {'b': b})
class Admin(forms.ModelForm):
    class Meta:
        model=models.admin
        fields=["usernum","password","username"]
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环找到所有的插件,添加class=“form——control”
        for name, field in self.fields.items():
           # if name=="password":
            #    continue
            field.widget.attrs = {"class": "form-control"}
def admin_add(request):
    if request.method == "GET":
       admin=Admin()
       return render(request, 'admin_add.html', {'admin': admin})
    #用户POST提交数据,数据校验
    admin=Admin(data=request.POST)
    if admin.is_valid():
        #如果数据合法,保存到数据库
        admin.save()
        return redirect('/admin/list/')
    #校验失败
    return render(request, 'admin_add.html', {'admin': admin})
def admin_edit(request,nid):
    """"编辑管理员"""
    row_object = models.admin.objects.filter(id=nid).first()
    if request.method == "GET":
        # 根据id去数据库获取要编辑的那一行数据
        admin =Admin(instance=row_object)
        return render(request, "admin_edit.html", {'admin': admin})
    admin=Admin(data=request.POST,instance=row_object)
    if admin.is_valid():
        # 如果数据合法,保存到数据库
        admin.save()
        return redirect('/admin/list/')
    return render(request, "admin_edit.html", {'admin': admin})
def admin_delete(request,nid):
    """"删除管理员"""
    models.admin.objects.filter(id=nid).delete()
    return redirect('/admin/list/')
#违规
def rule_list(request):
    b = models.break_rule.objects.all()
    return render(request, 'rule_list.html', {'b': b})
class Rule(forms.ModelForm):
    class Meta:
        model=models.break_rule
        fields=["readerid","bookid","overdue","destory"]
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环找到所有的插件,添加class=“form——control”
        for name, field in self.fields.items():
           # if name=="password":
            #    continue
            field.widget.attrs = {"class": "form-control"}
def rule_add(request):
    if request.method == "GET":
       rule=Rule()
       return render(request, 'rule_add.html', {'rule': rule})
    #用户POST提交数据,数据校验
    rule=Rule(data=request.POST)
    if rule.is_valid():
        #如果数据合法,保存到数据库
        rule.save()
        return redirect('/rule/list/')
    #校验失败
    return render(request, 'rule_add.html', {'rule': rule})
def rule_edit(request,nid):
    """"编辑管理员"""
    row_object = models.break_rule.objects.filter(id=nid).first()
    if request.method == "GET":
        # 根据id去数据库获取要编辑的那一行数据
        rule=Rule(instance=row_object)
        return render(request, "rule_edit.html", {'rule': rule})
    rule=Rule(data=request.POST,instance=row_object)
    if rule.is_valid():
        # 如果数据合法,保存到数据库
        rule.save()
        return redirect('/rule/list/')
    return render(request, "rule_edit.html", {'rule': rule})
def rule_delete(request,nid):
    """"删除管理员"""
    models.break_rule.objects.filter(id=nid).delete()
    return redirect('/rule/list/')
# ###############################登录#############################################
""""用户登录"""
class LoginForm(forms.Form):
    reader_id=forms.CharField(
        label="学号",
        widget=forms.TextInput,
        required=True
    )
    password=forms.CharField(
        label="密码",
        widget=forms.PasswordInput,
        required=True
    )
    def clean_password(self):
        password = self.cleaned_data.get("password")
        return md5(password)
def login(request):
    if request.method=="GET":
        form = LoginForm()
        return render(request, 'login.html', {'form': form})
    form=LoginForm(data=request.POST)
    if form.is_valid():
        #去数据库校验用户名和密码是否正确,获取用户对象
        admin_object=models.reader.objects.filter(reader_id=request.POST.get('reader_id'),password=request.POST.get('password')).first()
        if not admin_object:
            form.add_error("password","用户名或密码错误!")
            return  render(request,'login.html',{'form':form})
        #网站生成随机字符串
        request.session["info"]={'reader_id':admin_object.reader_id,'password':admin_object.password}
        return redirect('/reader/first/')
    return render(request,'login.html',{'form':form})
"""""管理员登录"""
class LogForm(forms.Form):
    usernum=forms.CharField(
        label="管理员账号",
        widget=forms.TextInput,
        required=True
    )
    password=forms.CharField(
        label="密码",
        widget=forms.PasswordInput,
        required=True
    )
    def clean_password(self):
        password = self.cleaned_data.get("password")
        return md5(password)
def log(request):
    if request.method=="GET":
        form = LogForm()
        return render(request, 'log.html', {'form': form})
    form=LogForm(data=request.POST)
    if form.is_valid():
        #去数据库校验用户名和密码是否正确,获取用户对象
        admin_object=models.admin.objects.filter(usernum=request.POST.get('usernum'),password=request.POST.get('password')).first()
        if not admin_object:
            form.add_error("password","用户名或密码错误!")
            return  render(request,'log.html',{'form':form})
        #网站生成随机字符串
        request.session["info"]={'usernum':admin_object.usernum,'password':admin_object.password}
        return redirect('/book/list/')
    return render(request,'log.html',{'form':form})