我第一次拿到“悦读圈图书共享系统”这个题目时,心里想的是:这不就是图书借阅的增删改查吗?真正动手梳理需求后才发现完全不是这么回事。这个题目最考验人的地方在于,它把共享、借阅、捐赠三条业务线压进了同一个系统里,而Django后端和微信小程序之间还隔着身份认证、状态同步、ISBN图书规范化等一系列看不见的工作量。
后来我按毕业设计答辩的标准把整套系统做完,从需求梳理、后端设计、小程序开发到联调部署前前后后用了两周多。这篇就把过程中真正有价值的部分写透,重点涉及Django借阅状态机设计、事务并发控制、扫码借书的完整链路,以及联调阶段那些能把人逼疯的怪问题。适合正在做图书共享/借阅/捐赠类毕设,或者想快速上手Django加微信小程序全栈项目的同学参考。
1. “悦读圈”这类题目,真正要解决的是什么需求
很多同学看到这类题目,第一反应是打开Django admin,建一张Book表然后开始写增删改查。等被指导老师问一句“共享和借阅有什么区别”“捐赠之后这本书归谁”,现场多半会卡壳。先把业务想清楚,比先写代码重要得多。
1.1 三种角色、三条业务链,别把它们当成一张表
一个完整的图书共享系统里,最基础的角色有三种:
- 普通用户:可以上传自己闲置的书,也可以借阅别人共享的书,还能提交捐赠意向。
- 平台管理方:审核捐赠、处理异常订单、维护书目数据,通常就是你自己或者图书馆管理员。
- 系统游客:在未登录状态下可以浏览书库,但触发借阅、收藏、评论等行为时必须登录。
对应到业务,至少有三条不能互相混淆的链路:
- 共享借阅链:用户上架图书,其他用户浏览检索并发起借阅,借阅到期后归还,书重新回到可借状态。
- 捐赠处理链:用户提交捐赠申请,管理员审核图书品相和信息,通过后录入库存(所有权转移给平台),不通过则退回。
- 轻社区链:悦读圈这个“圈”字暗示了社区属性,比如对某本书写短评、点赞、收藏某个书单。但如果项目重心是共享和借阅,社区功能要做到足够轻,别把用户评价、消息通知、帖子管理都堆进来,否则工作量会失控。
我见过不少项目把用户上传的书、平台库存、捐赠入库的书全塞在同一张表里,最后统计数据时根本分不清哪些是用户共享的、哪些是平台资产。为了避免这种混乱,数据模型上一定要把“书目信息”和“实体书副本”分开。这个我会在第2章详细展开。
1.2 从找书到还书的完整故事线
我习惯在写代码前,先把一条完整的用户故事线画出来,这样后面建表、写接口都不会漏字段。一个最基本的共享借阅流程是这样的:
- 用户A登录小程序,给一本闲置书拍照、填书名作者ISBN等信息,提交上架。
- 用户B在首页或书库浏览,通过搜索、分类或扫码找到这本书,看到状态是“可借”。
- 用户B点击借阅,系统生成一条借阅预约记录,书本状态从“可借”变成“待取/被预约”。
- 两人线下见面或通过平台约定取书方式,B确认取走,状态变为“借出中”。
- 阅读一段时间后B归还,状态变为“已归还”,A可以选择重新上架或转为捐赠。
这里的关键点是:图书的“物理状态”和“借阅记录的流转状态”是两个维度,必须在设计初期分清。物理状态描述这本书当前是否在架、是否被别人拿走;流转状态描述一条借阅申请目前处于哪个阶段。把这两个概念混在一起,到写查询逻辑时一定会乱。
1.3 为什么“圈的属性”建议后置
有些同学看到悦读圈,第一反应是做一个像论坛一样的书评社区,花大量时间做发帖、回帖、关注、私信,结果核心的图书流通逻辑反而做得粗糙。我的建议是,在B端和C端核心闭环没跑通之前,先不要做社区。
“圈”的轻量替代方案有很多,最实用的是给每本书加一个短评字段,用户归还后可以填写阅读体验,管理员审核后展示在图书详情页。这样既有“圈”的味道,又不破坏系统主结构。等共享借阅捐赠全部跑通,还有余力时,再去加独立书评模块也不迟。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Django后端骨架:数据模型、事务与借阅状态机
后端是整套系统的心脏。选Django的好处是ORM、Admin后台、认证体系都是现成的,一个学生项目两三天就能把基本架子搭起来。但架子搭得快不代表逻辑做得深,这一章会重点讲最容易被忽视的模型设计和状态流转。
2.1 App拆分与数据库选型
按照功能边界,我建议至少拆成下面几个App,不要所有模型堆在同一个models.py里:
- users:用户模型,继承Django的AbstractUser。
- books:书目信息、实体书副本、图书分类。
- borrow:借阅记录、预约记录、归还记录。
- donation:捐赠申请单、审核记录。
- community:轻量书评、点赞等(可视进度决定)。
数据库如果只是做毕设或者演示,直接使用Django默认的SQLite就够了,迁移、备份、部署几乎零成本。如果老师明确要求MySQL,也建议开发阶段先用SQLite,最后上线前再切换数据库并重新跑一遍迁移。为了切换顺畅,模型层千万不要写某个数据库特有的字段类型。
框架方面,纯接口用Django原生视图加JsonResponse反而最可控,适合规模不大的项目。DRF虽然能省不少序列化代码,但对新手来说要额外理解Serializer、ViewSet、权限类这些概念,如果时间紧容易踩坑。我最终采用了原生视图加模块化的service函数,接口逻辑清楚,答辩时也更好讲。
2.2 核心模型字段设计:书目与副本分离
前面提到的“书目信息”和“实体书副本”分离,落地成代码大概是这样的:
python复制# books/models.py
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
class Category(models.Model):
name = models.CharField(max_length=32, unique=True)
class BookInfo(models.Model):
# 一本“书”,以ISBN或书名作者去重
isbn = models.CharField(max_length=20, db_index=True, blank=True, default='')
title = models.CharField(max_length=128)
author = models.CharField(max_length=64, blank=True, default='')
publisher = models.CharField(max_length=64, blank=True, default='')
cover = models.URLField(blank=True, default='')
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
created_at = models.DateTimeField(auto_now_add=True)
python复制#
