1. 系统简介
该实验设计开发一个简单的图书管理数据库系统,包括图书馆内书籍的信息、学校在校师生的信息以及师生的借阅信息。此系统用户面向图书管理员和借阅读者,图书馆管理员可以完成图书、读者等基本信息的增加、删除和修改、查看;读者可以进行图书的借阅、查看、预约等操作。构建基于B/S架构,MySQL数据库为基础,应用Django框架建设过程和方法。本系统主要包含以下基本功能,主要是前台展示和后台管理两部分,其中前台展示包括登陆模块、首页展示、书籍检索、分类查看等。
系统开发技术及工具:Python Django HTML MySQL数据库 Windows11系统 PyCharm
- 2.系统分析
- 2.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,书名,作者,出版社,出版日期,价格,总量,余量等九个属性,便于读者在使用图书馆管理系统时,更加准确的定位到所选图书的位置,了解图书的信息。也可以方便读者利用碎片化的信息,从大量的图书中筛选自己可能心仪图书。
2、图书馆管理员实体E-R图
图书管理员实体具有编号,账号,密码,姓名,联系方式
3、读者实体E-R图
读者具有读者编号,读者姓名,联系电话,邮箱地址,备注,便于图书管理员及时的维护管理借阅系统,明确每一本图书的去向,对与图书馆图书的情况有一个把握。维护图书管理系统的正常运行。
4、总体E-R图
在图书管理系统中,一名读者可以借阅多本图书,多名图书管理员同时管理多本图书,一名读书管理员可以同时管理多名读者。通过实体之间的相互联系,构成了图书管理系统的总体E-R图。
3.3表设计
1、读者表(reader)
列名 | 类型 | 长度 | 约束 | 备注 |
id | int | 主键 | 编号 | |
reader_id | int | 11 | 学号 | |
password | char | 20 | 密码 | |
name | char | 10 | 读者姓名 | |
telephone | char | 15 | 联系电话 | |
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 | 外键 | 藏书类型 |
- 管理员用户表(admin)
列名 | 类型 | 长度 | 约束 | 备注 |
id | Int | 主键 |
| |
usernum | Char | 20 |
| |
password | Char | 11 |
| |
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 | 联系电话 | |
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 | 外键 | 藏书类型 |
- 管理员用户表(admin)
列名 | 类型 | 长度 | 约束 | 备注 |
id | Int | 主键 |
| |
usernum | Char | 20 |
| |
password | Char | 11 |
| |
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 | 联系电话 | |
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 | 外键 | 藏书类型 |
- 管理员用户表(admin)
列名 | 类型 | 长度 | 约束 | 备注 |
id | Int | 主键 |
| |
usernum | Char | 20 |
| |
password | Char | 11 |
| |
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工具进行本次项目的制作
- 创建django项目
目录说明:
manage.py:一个命令行工具,可以说Django项目就是从这个文件开始执行的。
_init _.py:一个空文件,表示mytest应该被看做一个python包;
settings.py:整个项目的配置参数文件;
urls.py:项目的URL声明,一般项目的顶级url正则匹配放置在这里;
wsgi.py:项目与WSGI兼容的Web服务器入口;
2.创建应用
(1)项目创建完成后需要有具体的应用
(2)创建后生成目录:
admin.py: 模型注册和后台管理相关的文件;
_init_.py: 应用应该被看做一个Python包;
migrations: 用来放置应用模型的迁移脚本文件;
models.py: 定义模型;
test.py: 放置项目的测试文件;
viems.py: 定义视图;
(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配置模板和静态文件
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.bookfields=["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":#continuefield.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.readerfields=["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":#continuefield.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.adminfields=["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":#continuefield.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_rulefields=["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":#continuefield.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","用户名或密码错误!")returnrender(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","用户名或密码错误!")returnrender(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})