每年毕业设计咨询季,我都会收到一批类似的问题:学长,用django+python做微信小程序的大学学生返校疫情管理系统,这个题该怎么下手?很多人看到题目第一反应是“这东西是不是已经过时了”,但真正做过之后你会发现,它恰好是一个很经典的“多角色流程审批”场景,把Django后端开发、微信小程序前端、数据库设计、权限控制和前后端联调全部串在一条完整业务链路里。工作量可控、演示效果好,论文里的图表和测试用例也特别好写,所以它非但没有过时,反而是计算机专业毕业设计里最容易出成果的一类题目。
这篇内容我按照一套可跑通系统的标准来拆解,从需求梳理、后端设计、小程序端落地,到本地联调、部署排错和论文呈现,把每个环节的关键决策和踩坑点都讲清楚。已经选了类似题目的同学可以照着做,还没定题目的看完也能判断这题到底适不适合自己。
1. 先看清课题的本质:这不是“疫情系统”,而是一套流程审批平台
1.1 需求方到底要什么:返校场景背后的角色与流程
拿到这个题目的大部分同学,第一反应都是把重心放在“健康数据”上——体温、症状、位置,恨不得做十个录入页面。但如果你站在学校管理者的角度想,他们要的其实不是另一个打卡工具,而是一套能支撑返校安排的审批管理平台。
学生返校之前,学校需要确定几件事:你从哪里回来、最近健康状况怎么样、有没有接触过风险人群、是否需要隔离观察。围绕这些信息产生的动作是:学生提交健康信息和返校申请,辅导员进行初审,学院管理员确认最终名单,校医院或后勤部门获取异常数据汇总,系统管理员负责账号和基础配置。这一条链路走下来,本质就是一个带着“审批流”的信息收集与状态管理平台。
所以做这个题的第一步不是写代码,而是把业务流程图画出来,把所有角色和状态转换列清楚。我建议至少分出四类角色:
- 学生:每日健康上报、发起返校申请、查看审批结果。
- 辅导员:审核所带班级的返校申请、查看异常提醒。
- 学院管理员:做校级汇总与终审、导出统计报表。
- 系统管理员:维护账号、专业班级等基础数据、管理字典配置。
角色都不复杂,但每类角色的权限边界必须清晰,这直接决定了后面Django端的接口设计和权限控制怎么做。
1.2 为什么是 Django + 微信小程序这个组合
这个技术组合能被反复选中,确实不是偶然。Django自带用户认证、ORM、Admin后台和表单校验,管理信息系统这种封闭业务场景,几乎是它天然的舒适区。你不需要像用Spring Boot那样准备一大堆繁琐配置,写完模型、配好路由、挂上视图,一个最简单的管理端就出来了。
小程序端的优势更直接:学生不需要安装App,微信扫码就能打开。小程序原生的表单、列表、卡片组件对这类业务界面非常友好,同一套页面做完,代码量比同功能的Android原生少一半以上。再加上这两年各高校都在用企业微信、微信生态做校园服务,小程序作为毕业设计选题,在需求合理性这一关就很好解释。
不客气地说,这个课题用Java或PHP也能做,同样能毕业。但在“信息收集—审批—汇总”这条路上,Django自带的后台可以直接给管理员使用,省掉大量自建页面和前端表格的工作量。这就是我优先推荐Django的理由,后面你会体会到这个选择有多省时间。
1.3 技术边界:哪些功能必须做,哪些写进论文但不实现
做毕业设计最忌讳需求失控。我见过太多人一开始把“轨迹分析”“疫情预测”“消息推送”全塞进来,结果做到一半发现根本做不完,答辩前一周又疯狂删功能,整个系统的完整性反而没了。
我给一个经过验证的功能边界:
- 核心功能A:学生健康信息填报,包含体温、症状、风险接触情况、当前所在位置。
- 核心功能B:返校申请与审批,包含申请提交、辅导员初审、学院管理员终审。
- 核心功能C:学生端查看个人状态和审批结果。
- 核心功能D:管理端数据查询、统计报表、Excel导出。
- 加分功能:异常数据自动标红、按学院/班级健康统计趋势图、返校名单导出。加分功能做简化版就行,页面和数据流必须有,但不一定追求大而全,它主要是为论文“创新点”章节服务的。
先把边界划清楚,再把流程图画明白,开发节奏才不会被拖垮。很多同学失败,不是技术不行,而是从一开始就没想清楚自己要交付什么。
2. Django 后端的核心:角色体系、模型关系和 API 设计
2.1 用户模型怎么设计:扩展 User 还是单独建表
Django自带的User模型提供了用户名、密码、邮箱这些基础字段,但缺少“学号”“班级”“角色”这类业务概念。常见的做法有两种:一是直接在User模型上增加字段,二是建一张Profile表和User做一对一关联。
我推荐后者。新建一个Profile模型,保存角色枚举和业务身份字段,这样所有业务查询都集中在Profile上,不污染Django内置表,也能避免以后想升级Django版本时被自定义User表拖累。
from django.contrib.auth.models import User from django.db import models class Profile(models.Model): ROLE_CHOICES = ( (1, 'student'), (2, 'counselor'), (3, 'college_admin'), (4, 'system_admin'), ) user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile') role = models.SmallIntegerField(choices=ROLE_CHOICES, default=1) student_no = models.CharField(max_length=20, blank=True) college = models.CharField(max_length=50, blank=True) major = models.CharField(max_length=50, blank=True) class_name = models.CharField(max_length=50, blank=True) phone = models.CharField(max_length=20, blank=True) created_at = models.DateTimeField(auto_now_add=True)角色用IntegerField存数字枚举,比存字符串更规范,也方便权限判断时直接比较大小。业务代码里通过request.user.profile.role就能拿到当前身份,不用到处判断User.username。
2.2 核心业务表:健康上报、返校申请、审批记录
业务表重点看三张:HealthReport(健康上报)、ReturnApplication(返校申请)、ApprovalRecord(审批记录)。
健康上报表里有一个最容易忽略的约束:每个学生每天只能上报一次。这个约束最稳妥的实现是数据库层的unique_together,而不是在业务代码里先查询再判断。因为并发请求时,代码层的“先查后写”会出竞态问题,数据库唯一约束才是硬保证。
class HealthReport(models.Model): student = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='reports') report_date = models.DateField() temperature = models.DecimalField(max_digits=4, decimal_places=1) has_symptom = models.BooleanField(default=False) symptom_desc = models.CharField(max_length=200, blank=True) has_risk_touch = models.BooleanField(default=False) current_location = models.CharField(max_length=100, blank=True) remark = models.TextField(blank=True) created_at = models.DateTimeField(auto_now_add=True) class Meta: unique_together = ('student', 'report_date')返校申请表的重点在审批状态,我建议用IntegerField做状态机:1待审核、2辅导员已通过、3学院已通过、4已驳回。同时预留一个content字段存审批意见,方便老师驳回时说明原因。审批记录表记录每一次动作,包括操作人、操作时间、操作前后状态,这是论文里“审批痕迹追踪”功能的依据,答辩时也是加分点。
2.3 RESTful 接口设计:API 列表与登录方案
接口层建议直接用Django REST Framework,别自己造轮子手写JSON序列化。接口按业务模块划分如下:
- 认证类:/api/auth/login、/api/auth/logout
- 健康上报:/api/health/report(POST提交)、/api/health/report?date=xxx(GET查询)
- 返校申请:/api/return/apply、/api/return/list
- 审批类:/api/audit/pending(待审核列表)、/api/audit/approve(执行审批)
- 统计类:/api/stats/summary、/api/stats/export
登录方案上,小程序端推荐使用JWT,而不是Django默认的Session。原因是小程序不像浏览器那样自带Cookie机制,前端每次请求手动把Token放在请求头里,调试和维护都更方便。具体做法是用djangorestframework-simplejwt这个库,替换DRF的默认认证类。
接口URL的命名尽量语义化,别用/api/getdata这种含糊路径,答辩老师看接口设计时,合理的URL本身就是系统设计能力的体现。
2.4 定时任务与统计模块:不用急着上 Celery
很多教程一提到定时任务就推荐Celery,但对毕业设计这个规模来说,Celery有点杀鸡用牛刀。Django的management command完全能胜任:写一个python manage.py daily_sync命令,里面执行健康数据汇总、状态提醒更新,然后用系统的cron或者云平台的定时触发器每天调用一次即可。
统计模块我用Django ORM的annotate,按日期统计上报人数、按学院统计异常数。这些数据通过一个接口返回给小程序端或管理后台,前端用图表库渲染。看起来不复杂,但论文里“系统测试与数据分析”这一章,数据都从这里来,工作量一下子就充实了。
3. 微信小程序端如何落地:登录态、表单交互和接口联调
3.1 登录流程:wx.login 获取 code,后端换 openid
小程序端最耗时间的通常不是页面UI,而是登录流程。你要记住一件事:小程序的用户识别靠openid,不靠账号密码。标准流程是:
- 页面onLoad时调用wx.login,拿到一个临时code。
- 通过wx.request把code发给Django接口。
- Django后端用code向微信服务端换openid和session_key。
- 后端根据openid查找或创建User,签发JWT返回给小程序。
- 小程序把token存到wx.setStorageSync,之后所有请求自动带上token。
这里有个很隐蔽的坑:小程序code的有效期只有五分钟,而且只能用一次。如果前端因为网络抖动连续调用了两次wx.login,第二个code就会失效。所以前端要做节流,用一个isLogging标志位拦住重复登录请求,避免无意义的报错。
3.2 页面结构设计:页面不在多,够用就好
页面数量我建议控制在六到七个:首页、健康上报页、返校申请页、申请记录列表页、审批列表页、统计页、个人中心。毕业设计不需要做成一款商业化产品,页面太多反而给自己增加联调负担。
首页建议做成“状态卡片”式:显示最近一次上报日期、体温是否正常、审批进度。需要特别注意的是自定义导航栏。小程序的默认导航栏在不同机型上高度不一致,如果页面结构用了自定义导航栏,需要先通过wx.getSystemInfoSync拿到状态栏高度和菜单按钮位置,再动态计算导航栏高度,否则在带刘海屏的设备上会出现内容塌陷。
表单里的单选、下拉选择,优先用小程序原生的radio-group和picker,别为了好看引入复杂的自定义弹层。返校申请里的“交通方式”“学院”这些字段,用picker就能解决,维护成本低,答辩时也不会因为组件显示异常而出丑。
3.3 wx.request 封装与常见错误排查
三分业务,七分联调。小程序和后端联调中遇到的大部分问题,根源都在网络请求上。我习惯封装一个统一的request方法,把baseURL、header、token注入、错误码统一处理都放在一个文件里。
// utils/request.js const BASE_URL = 'https://your-domain.com/api'; function request(path, method = 'GET', data = {}) { return new Promise((resolve, reject) => { wx.request({ url: BASE_URL + path, method: method, data: data, header: { 'Content-Type': 'application/json', 'Authorization': 'JWT ' + wx.getStorageSync('token') }, success: (res) => { if (res.statusCode >= 200 && res.statusCode < 300) { resolve(res.data); } else if (res.statusCode === 401) { wx.removeStorageSync('token'); wx.navigateTo({ url: '/pages/login/login' }); } else { reject(res.data); } }, fail: (err) => { reject(err); } }); }); }联调时我遇到过最多的问题,按出现频率排是这样:
- 本地地址不通:模拟器里能访问localhost,真机不行。真机调试时改用电脑的局域网IP,同时确认手机和电脑连的是同一个Wi-Fi。
- 接口返回但页面没数据:八成是后端没有用JSON格式返回,或者字符串含中文时没设置ensure_ascii=False。
- 请求报错类似10002这类网络超时错误:排查顺序永远是后端服务有没有起来、前端URL对不对、服务器端口有没有放行、手机网络能不能通到目标IP。别一上来就怀疑代码逻辑,看控制台看日志比瞎猜快得多。
如果你手头有抓包工具,比如Charles,也可以用来观察小程序真实发出的请求头和响应体。特别是排查“请求头没带token”“后端返回了意外字符”这类问题时,抓包能直接看到最原始的数据,比在代码里打日志更直观。
3.4 表单校验与用户体验细节
健康上报表单里,体温合理范围建议限制在34到42度之间,超出直接前端拦截。风险接触选“是”时,强制要求补充说明。这些校验在前端做一遍,给用户即时反馈;后端再做一遍,防止有人绕过前端直接调接口。
我还有一个使用习惯:表单提交后不直接跳转,而是先提示成功,再延迟约半秒自动返回首页。用户会觉得反馈很顺滑。申请记录列表做下拉刷新,状态变化时用户能及时看到最新结果,这些细节在答辩现场演示时很能体现工程素养。
4. 让数据安全不是一句空话:权限隔离与隐私保护细节
4.1 接口级权限:怎么区分学生、辅导员和管理员
很多学生项目的问题不是功能少,而是接口权限几乎没有。任何登录用户把请求里的student_id改一改,就能看到别人的健康记录,这在答辩现场被老师试出来会非常尴尬。
DRF的权限控制其实很优雅。为每个接口设置permission_classes,再自定义一个基于角色的权限类:
from rest_framework.permissions import BasePermission class IsStudent(BasePermission): def has_permission(self, request, view): return request.user.is_authenticated and getattr(request.user.profile, 'role', None) == 1更关键的是get_queryset方法。学生查询数据时,强制过滤当前登录用户自己的数据,而不是信任前端传过来的student_id。辅导员查询时过滤班级字段。这样即使接口被人猜到,越权也拿不到数据。
4.2 数据脱敏与最小化采集
健康数据属于明确的隐私数据,展示逻辑要有讲究。列表页只显示学号后四位、打码姓名、日期、状态;导出Excel时才允许选择完整信息,并且记录操作日志。小程序接口返回的字段也不要全量给,用DRF的Serializer配置fields,只序列化前端真正需要的字段。
很多人写接口习惯model.objects.values()一把梭,把所有字段都返回给前端,这是非常不专业的做法。合理的最小化采集,既保护隐私,又减少网络传输量,答辩时还能作为系统的安全设计亮点来讲。
4.3 token 过期、HTTPS 和日志审计
JWT默认过期时间一小时,用户在页面停留稍长,后续请求就会401。好的体验是封装层遇到401时自动刷新token;不做自动刷新,至少也要优雅跳转到登录页,而不是白屏。token刷新接口要单独设计,不能简单复用登录接口。
线上环境微信小程序强制要求HTTPS和备案域名,这在毕业设计里绕不开。本地联调可以关闭开发者工具的域名校验,但答辩部署时一定要用HTTPS。申请免费证书、配置Nginx的步骤不复杂,第5章我展开说。
日志方面,Django的LOGGING配置把请求的method、path、user_id记录到文件,但不要记录完整的健康详情和token本身。这个“最小化日志”原则,在论文的安全性设计里可以专门写一段。
5. 本地联调与部署阶段的典型障碍
5.1 微信开发者工具和 Django 本地服务的互通规则
本地开发阶段,小程序开发者工具模拟器可以直接访问localhost端口。所以Django跑在127.0.0.1:8000,开发者工具里把接口地址填成http://127.0.0.1:8000/api/xxx,是能通的。很多人卡住的点是:模拟器能通,一旦点“真机调试”就不行了。原因很简单,手机不在开发机本地,自然访问不到127.0.0.1。真机调试时要用电脑的局域网IP,比如http://192.168.x.x:8000,同时Django的ALLOWED_HOSTS要加上这个IP。
另一个常见的坑是Windows电脑上第一次跑Django时,报错信息很长,很多人直接懵了。其实绝大多数情况是8000端口被占用或者MySQL驱动没装,看完整报错最末尾的几行,定位会比在网上搜原文快得多。
5.2 跨域、CSRF 和 Django 中间件调整
前后端域名不同,理论上会有跨域问题。但小程序不是浏览器,不存在传统意义上的CORS限制,这一点能给你省下很多麻烦。需要留意的是Django的CSRF中间件,它默认会拦截非表单POST。小程序以JSON方式发POST,如果还开着CsrfViewMiddleware,就会一直403。解决办法是对API视图加@csrf_exempt,或者在DRF配置里去掉Session认证,改用JWT认证。
顺带说一句,很多实现教程里推荐的django-cors-headers,在小程序开发场景其实可以不装,装了也不起决定性作用。别给自己加不必要的依赖。
5.3 MySQL、时区和中文乱码:先避开这些默认坑
数据库我推荐用MySQL,虽然SQLite也能跑,但论文里用MySQL更正式。建库时字符集指定utf8mb4,不然中文写入会莫名报错。Django的TIME_ZONE设置为Asia/Shanghai,USE_TZ一般保持True,但要注意DateTimeField存的是UTC时间,前端展示时需要转成本地时区,否则时间总是看起来少了八小时。
字段设计上还有一个建议:不要用数据库关键字做字段名,比如name、desc虽然Django会处理,但遇到复杂查询时会增加不必要的坑。命名统一用student_no、class_name这类前缀明确的风格。
5.4 小程序包体积超限和线上部署
微信小程序有2MB的包大小限制。如果开发者工具提示类似source size 2612kb exceed max limit 2mb的报错,说明代码包超了,无法真机预览。解决办法有三个方向:不用的图片放到云存储或CDN,别塞在本地;尽量用原生组件,不要引入大型UI库;拆分成主包和分包,低频页面用subpackages懒加载。我见过很多人因为一个图表库就把包打到2.5MB,其实换一种轻量实现,包体积立刻降下来了。
后端部署用Nginx加gunicorn或uwsgi,配上免费HTTPS证书。这一步既是线上运行的前提,也是论文部署章节的素材。如果不想自己买服务器,腾讯云或阿里云的轻量应用服务器就够,学生认证通常有优惠。
6. 从项目到毕业论文:测试、图表和工作量的呈现方法
6.1 测试用例怎么写才像真实工作
论文里的测试章节不能只贴运行截图。规范的写法是设计测试用例表,包含测试编号、前置条件、操作步骤、预期结果、实际结果。列举几个关键用例:
- 学生提交健康上报成功后,数据库记录条数增加一条。
- 同一学生同一天重复提交,接口返回重复上报错误。
- 普通学生请求辅导员审批接口,返回403。
- 审批通过后,学生端申请状态由待审核变为已通过。
如果时间允许,用Django的TestCase写核心接口的单元测试,源码里带上测试代码,答辩老师看到这个印象分会立刻不一样。测试不需要覆盖全部,覆盖核心链路就够了。
6.2 论文需要的图和表:结构、画法与组织
毕业设计论文里最核心的三张图是系统用例图、系统架构图和E-R图。画图要有逻辑:用例图标清角色和功能边界,架构图标清小程序、Django、数据库三层关系,E-R图把关键实体和联系表示清楚。
画图可以用draw.io或ProcessOn,画完导出矢量图再插入论文。需要注意:E-R图里的实体名和字段名,要与数据库设计保持一致,答辩老师一旦顺着图中实体去提问,名字对不上会非常尴尬。数据库表结构在论文附录里用表格整理,四列就够了:列名、类型、约束、说明。
性能测试和功能测试的表格也按统一格式排版,整篇论文的图表风格保持一致,看起来很专业。
6.3 演示与答辩侧重点:让系统在十分钟内讲明白
答辩演示不要从头到尾点菜单,而是按业务故事线走:
- 登录小程序端学生账户,现场演示健康上报和返校申请提交。
- 切到管理后台,演示待审核列表和审批操作。
- 再切回学生端,展示申请状态变化。
- 最后展示统计报表和导出功能。
每个环节控制在两分钟以内。现场有条件的话,把两个窗口提前摆成左右分屏,学生端和管理端同时可见,效果会非常直观。答辩老师常见的问题之一是“系统怎么防止学生伪造健康数据”,这时你的“每日唯一上报约束、辅导员人工核实、异常状态自动标红”设计就派上用场了。答得有条理,比系统本身炫酷更重要。
“微信小程序登录获取手机号”也是答辩时可能被问到的一个点。如果你的系统设计里做了手机号绑定,可以讲清楚button组件open-type="getPhoneNumber"拿到加密数据后,后端再通过会话密钥解密的流程。没做的话,就直接说明当前账号体系基于openid,手机号不是必选项,属于最小化采集,这也是一个正当理由。
做这类毕业设计,我一直跟来问我的人说同一句话:答辩能不能过,取决于两件事,一是系统能不能跑通完整业务流程,二是你能不能把每个技术决策讲出理由。这套django+python微信小程序的大学学生返校疫情管理系统,流程清晰、角色分明、技术栈在学术界认可度高,剩下就是看你愿意花几天把细节打磨到什么程度了。遇到问题多翻微信官方文档和Django文档,多打日志,别在群里等着别人替你调代码。自己踩过的坑,到答辩那天就是最扎实的底气。