简介:这是一套面向计算机相关专业学生的Django图书管理系统实战项目,适用于毕业设计、课程设计、期末大作业及项目练习场景,尤其适合正在准备毕设或需要完整项目经验的学习者。资源包共59个文件,约3.49MB,包含16个Python源码文件、19个HTML模板页面、1个SQLite3数据库、1个CSS与1个SCSS样式文件,以及PDF与DOC格式的项目报告文档,另附README说明与依赖编译文件,结构完整、层次清晰。项目围绕图书信息管理、借阅流程与后台维护等核心模块展开,代码可直接运行,配套报告文档便于理解设计思路与实现细节。目前已有78人学习关注,适合希望快速掌握Django框架开发流程、积累完整项目案例的读者参考使用。
1. 从一份 Django 图书管理系统源码说起:它到底能帮你省下多少时间
如果你正在为毕业设计或期末大作业发愁,手里攥着 Python 和 Django 却不知道从哪下手,这套「Python 基于 Django 图书管理系统源码 + 报告文档」大概率能让你少熬三个通宵。它不是那种只有几个空壳页面的演示 demo,而是一套能跑通「图书录入 → 借阅 → 归还 → 库存统计」完整闭环的项目,附带一份可以直接参考结构的报告文档。适合谁?一是时间紧、需要快速搭出可演示系统的同学;二是想拿一个真实 Django 项目练手、把 MTV 模式跑通的新手。我见过太多人卡在「知道 Django 有 ORM 和 Admin,但不知道怎么串成一个业务系统」这一步,这份源码的价值就在于它把这条链路完整铺开了。下面我按「先跑起来 → 再拆结构 → 再改功能 → 最后避坑」的顺序,把这份资源拆开讲透。
2. 把项目跑起来:环境、依赖与数据库初始化
2.1 环境选型与依赖清单
拿到源码包后第一件事不是急着runserver,而是先把 Python 版本和依赖对齐。Django 对 Python 版本有硬性要求,Django 3.2 支持 Python 3.6~3.9,Django 4.x 则要求 Python 3.8 以上。这份图书管理系统常见做法是基于 Django 3.2 + Python 3.8 的组合,稳定且资料多。如果你本地是 Python 3.11,直接装 Django 3.2 可能会在cgi模块上报错,因为该模块在 3.11 被移除了。
先建虚拟环境,别把全局环境搞乱:
# 创建虚拟环境,python3.8 换成你本地的版本 python -m venv venv # 激活:Windows 用 venv\Scripts\activate,macOS/Linux 用下面这行 source venv/bin/activate # 升级 pip,避免装包时出现解析超时 pip install --upgrade pip虚拟环境激活后,命令行前面会出现(venv)标识。这一步的逻辑是隔离依赖,因为 Django 项目经常需要锁定版本,全局安装容易和别的项目冲突。参数上python -m venv比virtualenv更标准,Python 3.3 以后自带,不用额外装。
接着装依赖。源码包里通常有requirements.txt,没有的话按下面这份最小清单来:
# 核心框架,3.2 是长期支持版,适合课程设计 pip install django==3.2.16 # 数据库驱动,MySQL 用 mysqlclient,SQLite 则不需要 pip install mysqlclient # 图片处理,图书封面上传会用到 pip install pillowdjango==3.2.16锁定小版本是为了避免自动升级到 4.x 导致 API 不兼容。pillow是ImageField的硬依赖,缺了它一上传封面就报Cannot use ImageField because Pillow is not installed。mysqlclient只在用 MySQL 时需要,如果你图省事用 SQLite,这行可以跳过。
2.2 数据库配置与迁移
打开settings.py,找到DATABASES配置。用 SQLite 的话几乎不用改,默认就是它,数据库文件会生成在项目根目录。用 MySQL 则要改成:
# settings.py 数据库配置段 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'library_db', # 提前在 MySQL 里建好这个库 'USER': 'root', 'PASSWORD': 'your_password', # 换成你自己的密码 'HOST': '127.0.0.1', 'PORT': '3306', 'OPTIONS': { 'charset': 'utf8mb4', # 支持中文和 emoji,别用 utf8 }, } }ENGINE决定用哪个数据库后端,NAME是库名不是表名,utf8mb4比utf8多支持四字节字符,图书名里带生僻字或特殊符号时不会乱码。改完配置后执行迁移:
# 根据 models.py 生成迁移文件 python manage.py makemigrations # 把迁移应用到数据库,建表 python manage.py migrate # 创建后台管理员账号,按提示输入用户名密码 python manage.py createsuperusermakemigrations只生成描述变更的 Python 文件,不碰数据库;migrate才真正执行 SQL 建表。很多人改完模型直接migrate,发现没生效,就是因为漏了makemigrations。createsuperuser建的账号用来登录 Django Admin 后台,图书的增删改查在后台就能完成大半。
2.3 启动与首次登录
# 启动开发服务器,0.0.0.0 让同局域网设备也能访问 python manage.py runserver 0.0.0.0:8000浏览器打开http://127.0.0.1:8000/admin,用刚才的超级用户登录,能看到图书、借阅记录等模型就说明数据库通了。前台页面一般是http://127.0.0.1:8000/,具体路由看urls.py。如果前台报TemplateDoesNotExist,多半是模板路径没配对,检查settings.py里的TEMPLATES配置和DIRS列表。
3. 拆开 MTV:模型、视图、模板怎么串成借阅闭环
3.1 模型设计:图书、读者、借阅记录三张表
Django 的 ORM 把表结构写成 Python 类,这份系统的核心模型通常有三张。图书表存书名、作者、ISBN、库存;读者表可以复用 Django 自带的User,也可以单独建;借阅记录表是中间表,记录谁在什么时候借了哪本书、什么时候还。
# models.py 核心模型定义 from django.db import models from django.contrib.auth.models import User class Book(models.Model): title = models.CharField(max_length=200) # 书名 author = models.CharField(max_length=100) # 作者 isbn = models.CharField(max_length=13, unique=True) # ISBN 唯一 stock = models.IntegerField(default=1) # 库存数量 cover = models.ImageField(upload_to='covers/', blank=True) # 封面 def __str__(self): return self.title class BorrowRecord(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) # 借阅人 book = models.ForeignKey(Book, on_delete=models.CASCADE) # 所借图书 borrow_date = models.DateField(auto_now_add=True) # 借出日期 return_date = models.DateField(null=True, blank=True) # 归还日期 is_returned = models.BooleanField(default=False) # 是否已还ForeignKey建立外键关联,on_delete=models.CASCADE表示用户或图书被删时,相关借阅记录一并删除,避免脏数据。auto_now_add=True让借出日期在创建记录时自动填入,不用手动传。is_returned用布尔字段标记状态,比靠return_date是否为空来判断更直观,查询时filter(is_returned=False)就能拿到所有未还记录。
3.2 视图逻辑:借书与还书的库存扣减
借阅功能的核心不是插一条记录,而是「插记录 + 扣库存」要在一个事务里完成,否则并发下会出现库存扣成负数。常见做法是用transaction.atomic包住:
# views.py 借书视图 from django.db import transaction from django.shortcuts import redirect from .models import Book, BorrowRecord @transaction.atomic def borrow_book(request, book_id): book = Book.objects.select_for_update().get(id=book_id) # 行锁 if book.stock <= 0: return redirect('book_list') # 库存不足,直接返回 book.stock -= 1 book.save() BorrowRecord.objects.create(user=request.user, book=book) return redirect('my_borrows')select_for_update()在事务内对这条图书记录加行锁,防止两个请求同时读到库存为 1 然后都扣成 0。@transaction.atomic装饰器保证扣库存和建记录要么都成功要么都回滚。还书逻辑反过来,把is_returned置为True、填上return_date、库存加一,同样要包事务。这里有个容易忽略的点:select_for_update只在支持行锁的数据库上生效,SQLite 默认不支持,用 SQLite 调试时并发问题测不出来,上线换 MySQL 才暴露。
3.3 模板与路由:把数据渲染成页面
模板层负责把视图传来的 QuerySet 渲染成 HTML。图书列表页通常这样写:
<!-- templates/book_list.html 片段 --> {% for book in books %} <div class="book-item"> <h3>{{ book.title }}</h3> <p>作者:{{ book.author }} | 库存:{{ book.stock }}</p> {% if book.stock > 0 %} <a href="{% url 'borrow_book' book.id %}">借阅</a> {% else %} <span>已借完</span> {% endif %} </div> {% endfor %}{% for %}遍历视图传过来的books,{% url %}反向解析路由名生成链接,比硬编码/borrow/1/更稳,改路由时不用动模板。{% if book.stock > 0 %}控制借阅按钮的显示,库存为零时给个提示。路由在urls.py里用path('borrow/<int:book_id>/', views.borrow_book, name='borrow_book')定义,<int:book_id>会把 URL 里的数字捕获成整型参数传给视图。
4. 二次开发:把系统改成你自己的选题
4.1 加一个「图书分类」功能
原系统如果只有图书没有分类,答辩时容易被问「怎么按类别检索」。加分类不难,建个Category模型,给Book加外键:
# models.py 新增分类模型 class Category(models.Model): name = models.CharField(max_length=50) def __str__(self): return self.name # 在 Book 里加一行外键 class Book(models.Model): # ... 原有字段保持不变 category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True)on_delete=models.SET_NULL表示分类被删时图书的分类置空而不是连图书一起删,null=True允许图书暂时没有分类。改完模型记得makemigrations+migrate。然后在 Admin 里注册Category,后台就能维护分类了。视图里按分类筛选只需Book.objects.filter(category_id=cid)。
4.2 借阅期限与逾期提醒
课程设计里加个「借期 30 天,逾期标红」能明显提升完成度。在BorrowRecord上加个方法算逾期:
# models.py 给 BorrowRecord 加方法 from datetime import date, timedelta class BorrowRecord(models.Model): # ... 原有字段保持不变 @property def is_overdue(self): if self.is_returned: return False deadline = self.borrow_date + timedelta(days=30) return date.today() > deadline@property让is_overdue像字段一样在模板里用{{ record.is_overdue }}调用。timedelta(days=30)算出应还日期,和今天比较。模板里配合{% if record.is_overdue %}加个红色样式即可。注意borrow_date是DateField,和date.today()类型一致,别拿datetime.now()去比,会报类型错误。
4.3 报告文档怎么用才不浪费
附带的报告文档别只当模板抄格式,重点看三块:需求分析里的用例描述、数据库设计的 E-R 图、系统实现的模块划分。把这三块对应到你的源码结构上,答辩时老师问「你的借阅流程怎么设计的」,你能指着views.py里的borrow_book说清楚事务和行锁,比背稿子强。文档里的截图换成你自己跑起来的界面,查重也稳。
5. 避坑与排查:那些让我返工三次的问题
5.1 迁移报错 No changes detected
现象:改了models.py执行makemigrations提示No changes detected。原因通常是新模型所在的 app 没加到INSTALLED_APPS,Django 根本没扫描到。解决:在settings.py的INSTALLED_APPS里加上 app 名,再执行。如果还不行,检查models.py有没有语法错误导致导入失败。
5.2 静态文件 404
现象:页面样式全丢,控制台一堆 404。原因:DEBUG=True时 Django 才自动服务静态文件,且STATIC_URL和目录结构要对。解决:确认settings.py里STATIC_URL = '/static/',模板顶部{% load static %},引用写成{% static 'css/style.css' %}。上线DEBUG=False后要交给 Nginx 处理,这是另一个话题。
5.3 中文乱码
现象:图书名存进去变成问号。原因:数据库字符集不是utf8mb4,或连接没指定字符集。解决:建库时CREATE DATABASE library_db CHARACTER SET utf8mb4;,settings.py的OPTIONS里加'charset': 'utf8mb4'。已经建错库的,用ALTER DATABASE改字符集,但已有数据可能已经损坏,最好重建。
5.4 外键删除导致数据丢失
现象:删了一个用户,他的借阅记录全没了,统计对不上。原因:on_delete=models.CASCADE的连锁删除。解决:如果业务上要保留历史记录,把借阅记录的外键改成on_delete=models.SET_NULL并允许为空,或者用PROTECT禁止删除还有借阅记录的用户。选哪种取决于你的业务规则,别默认用 CASCADE。
5.5 runserver 能跑但换端口就访问不了
现象:runserver 8000正常,改成别的端口或0.0.0.0后局域网访问不了。原因:防火墙没放行,或绑定地址写成了127.0.0.1只监听本机。解决:用python manage.py runserver 0.0.0.0:8000,并在系统防火墙里放行对应端口。云服务器还要检查安全组规则。
6. 进阶技巧:用 Admin 的 list_display 和搜索把后台变成管理利器
默认的 Django Admin 只显示模型的对象名,图书多了根本没法用。花十分钟配置list_display、search_fields和list_filter,后台立刻好用十倍。在 app 的admin.py里:
# admin.py 后台定制 from django.contrib import admin from .models import Book, BorrowRecord @admin.register(Book) class BookAdmin(admin.ModelAdmin): list_display = ('title', 'author', 'isbn', 'stock', 'category') search_fields = ('title', 'author', 'isbn') # 顶部搜索框 list_filter = ('category',) # 右侧筛选栏 list_editable = ('stock',) # 列表页直接改库存 @admin.register(BorrowRecord) class BorrowRecordAdmin(admin.ModelAdmin): list_display = ('user', 'book', 'borrow_date', 'is_returned', 'is_overdue') list_filter = ('is_returned',) search_fields = ('user__username', 'book__title')list_display决定列表页显示哪些列,search_fields生成搜索框,list_filter生成右侧筛选,list_editable让你在列表页直接改库存不用点进详情。search_fields里user__username的双下划线是跨外键查询,Django 会翻译成 JOIN,这是 ORM 的常用写法。is_overdue是模型里的@property,也能直接放进list_display,但注意它不能排序,因为不是数据库字段。
再进一步,如果想让借阅记录导出成 Excel 方便统计,装个django-import-export,在BorrowRecordAdmin里继承ExportMixin就行。不过课程设计阶段没必要上太重,把上面这些配好,答辩演示时后台的搜索、筛选、直接编辑三个功能一亮,完成度就上去了。
验证配置有没有生效,最直接的办法是runserver后进/admin/,看图书列表页顶部有没有搜索框、右侧有没有筛选栏、库存能不能直接改。改完admin.py不用迁移,Django 自动重载。如果报admin.E108之类的错误,多半是list_display里写了不存在的字段名,对着models.py核对一遍。
从那以后我每次拿到 Django 项目,都强制先跑一遍makemigrations+migrate+createsuperuser三连,确认后台能登录再动业务代码,省得后面分不清是环境问题还是逻辑问题。希望帮到你。
本文还有配套的精品资源,点击获取