☰
基于Django的班务管理系统设计与开发实践
2026/9/30 8:28:11 网站建设 项目流程

1. 选题逻辑:为什么“班务管理系统”适合当毕业设计,又为什么选 Django

又到了一年一度被毕业设计支配的季节。如果你正在被“到底选什么题目”折磨,我建议你把“django班务管理系统”这种题目纳入考虑范围。不要觉得它听起来不够酷,事实上,“班务管理系统”在整个管理系统大类里,是一个特别适合本科阶段完成的题目:业务清晰、数据关系不复杂、有真实使用场景、也方便在答辩时把每个功能讲明白。相比“校园二手交易平台”“网上商城”“图书馆管理系统”这些已经被做滥的方向,“班务”这个切入点更贴近学生日常,评委听起来也会觉得有落地的感觉。

先解释一个关键点:为什么一直都在强调“django班务管理系统”而不是“springboot班务管理系统”?因为Django这个框架自带的东西,几乎就是为这类“面向中小型业务的管理系统”量身准备的。admin后台可以直接给你的数据模型生成一套管理界面,满足“班主任发布通知、查看记录”这类需求;自带的用户认证模块帮你解决登录、注册、权限判断;模板系统让你不需要单独拆一个前端项目就能把页面渲染出来。再加上ORM抽象掉了大部分SQL胶水代码,数据库表结构可以完全用Python类定义,这对计算机专业学生来说,能节省大量时间,把精力放在业务逻辑而不是环境配置上。

但你也别误会,我不是说用Django就万事大吉。恰恰相反,如果只是照着网上的教程搭一个能增删改查的壳子,那你连“及格”都谈不上。班务管理系统叫“系统”,就得有管理的样子:角色权限要区分开,数据状态要有流转,统计结果要能直接展示在页面上,甚至还要考虑删除数据时的约束关系。这些内容结合起来,才是一份能拿出来参与答辩、能写进毕业论文的毕业设计。

顺便说一句,很多同学手上拿到的是现成源码,标题里往往带着一串编号,比如“计算机毕业设计源码42534”。这串数字其实是平台或者卖家用来区分项目的流水号,不是技术指标,更不是版本号。真正决定这个设计值不值得用的,是源码目录是否完整、运行文档是否清晰、数据模型是否符合业务常识。后面我会专门用一个章节讲怎么检查源码、怎么运行、怎么在答辩前把它变成自己的东西,先往下看。

2. 先画业务边界:班务管理系统里到底管些什么

很多学生拿到题目之后的第一反应是“功能越多越好”,然后疯狂堆模块,最后系统里塞了通知、留言、聊天、选课、成绩、宿舍管理一大堆东西,每个模块都只有一张表,看起来像什么都做了,实际上什么都做不深。这是毕业设计里最典型的翻车操作。做“班务管理系统”第一步不是写代码,是画边界——搞清楚一个班的日常管理工作里,哪些必须由系统管,哪些暂时不用管。

2.1 功能模块不是越全越好,先分清主线和支线

把“班务”这个词拆开,它指的是班级日常事务。我按自己开发这套系统的思路,把业务分成四条主线:

第一,学生基础信息管理。这是整个系统的主角,学号、姓名、性别、生源地、联系方式、宿舍号、状态(在读/休学/毕业)。没有这张底表,其他所有功能都无从谈起。

第二,考勤与请假管理。日常上课有没有到、请假单谁来审批、最近一周出勤率是多少,这套流程是班务工作里最频繁的。

第三,活动与通知管理。班会记录、团日活动、班级聚会,谁参加了、哪个同学没参加;班主任发个通知,已读未读状态怎么跟踪。

第四条是基础数据支撑,比如班级信息、专业信息、学年学期、班主任和辅导员信息。这一条经常被忽略,但我建议把班级单独抽成一张表,学生表用外键关联班级。不然以后新增一个班,就得把学生的班级字段复制一遍,维护起来很痛苦。

除了主线,还可以加统计报表模块,比如按月份统计每个学生的出勤率、请假次数,也可以导出Excel。但请记住:统计报表是为了给上面的功能“赋能”,不是独立的炫技模块。一条清晰的主线要比五个粗糙的支线强得多。

2.2 数据库模型:谁是主角、谁是配角、谁是多对多

我用Django的Model定义来梳理数据库设计,核心关系大概是这样:

Student(学生)是主角,ClassInfo(班级)是配角,AttendanceRecord(考勤记录)和LeaveRequest(请假申请)是围绕学生产生的大量流水数据。Notice(通知)完全不依赖学生表,它是独立的业务实体。ClassActivity(班级活动)和Student之间就需要多对多关系,因为一个活动有多个学生参与,一个学生也参加过多次活动。

下面这张表是主要模型的设计思路:

模型关键字段外键/关联说明
ClassInfoname, major, counselor, room一对多关联Student班级基本信息
Studentstudent_no, name, gender, phone, dormitory外键指向ClassInfo学生基础信息,学号做唯一约束
AttendanceRecordstudent, date, status, remark外键指向Student每天一条考勤记录,用status表示出勤/迟到/请假/缺勤
LeaveRequeststudent, start_time, end_time, reason, status外键指向Studentstatus用于请假审批:待审核/已通过/已驳回
Noticetitle, content, publisher, is_top外键指向User发布通知的人通常是班主任
ClassActivitytitle, location, activity_time, organizer多对多关联Student记录活动参与情况

我把这套模型在Django里落地之后,第一感觉是“比想象中轻很多”。一个学生的一次请假,就是LeaveRequest里的一行记录;一次班会活动,就是ClassActivity的一行,外加关联表里的若干条参与记录。这样的数据模型写毕业论文的时候也特别好解释,ER图不复杂,关系说得清楚,答辩提问环节基本不会被难倒。

再补充一点关于删除约束的想法。Django的外键默认是on_delete=models.CASCADE,也就是删掉一个班级,整个班级的学生全部跟着删掉。这个默认行为一定要警惕,因为这在真实业务里是灾难。班级信息输错需要删除时,你是不可能让底下的学生档案一起消失的。我建议学生表的外键改成on_delete=models.SET_NULL,同时允许该字段为空,这样即使班级被删掉,学生的基本信息还在,只是“当前班级”置空。这是我在做毕设时踩过的一个非常大的坑,后面专门拿来分析。

3. 核心代码落地:从项目脚手架到可运行系统的关键步骤

业务边界画完了,接下来就是真正上手敲代码。这一节我按一个完整Django项目的标准流程来讲,从创建项目到把核心模块跑起来。就算你手里拿到的是现成源码,我建议你也自己动手走一遍这个流程,因为只有你自己创建过一次,才能看懂源码里的每个文件是干什么的。

3.1 项目初始化与应用划分

我通常在项目根目录用下面的命令创建项目:

django-admin startproject class_manage . python manage.py startapp students python manage.py startapp affairs python manage.py startapp notices

这里解释一下为什么这么拆应用。students应用负责学生、班级这些基础信息的CRUD;affairs应用负责考勤、请假、活动这些事务性流程;notices应用单独放通知公告。这样拆分的好处是业务隔离清晰,哪个模块出问题就直接去哪个应用里找,论文里的系统设计章节也好写。

然后开始注册应用、配置数据库。如果使用Django默认的SQLite,settings.py里基本不用改太多;但很多毕设要求用MySQL,你需要额外安装pymysql,并且在项目的__init__.py里写上:

import pymysql pymysql.install_as_MySQLdb()

然后才在settings.py里配置数据库连接信息。这个步骤是新手最容易忽略的,忘掉install_as_MySQLdb,启动时就会报ModuleNotFoundError: No module named 'MySQLdb'。我第一次遇到这个报错时,还以为是MySQL没装好,来回折腾了半天。

3.2 用户认证、权限与“班主任”角色

Django自带了一套User模型和认证机制,直接使用可以解决80%的登录问题。但毕业设计里一定要做出“角色”这个层级,否则班主任、班长、普通学生三个身份没有区别,整个系统就没有权限感。

我的建议是不要轻易改Django自带的User表,而是通过Group来管理角色。创建三个组:班主任、班长、学生。班主任拥有所有模块的操作权限;班长能发起考勤登记和活动报名;学生只能查看自己的考勤和请假状态、查看班级通知。做法是在视图函数上做一个小小的权限封装:

from django.contrib.auth.decorators import login_required, user_passes_test def is_class_teacher(user): return user.groups.filter(name="班主任").exists() @login_required @user_passes_test(is_class_teacher) def review_leave(request, leave_id): # 班主任审核请假单 pass

如果你拿到的是已有源码,一定要检查对方有没有处理权限问题。很多“简单管理系统”的源码,不管什么角色登录后都能访问所有页面,这种代码答辩的时候一被追问就穿帮。我自己在开发时用过django自带admin的超管账号做测试,后来导入真实数据时还专门建了三个测试账号,分别切换身份确认页面跳转和按钮状态是正确的。

还要注意,创建用户的时候密码一定要用set_password,不要直接明文存储:

from django.contrib.auth.models import User user = User.objects.create_user(username="20230001", password="123456") user.groups.add(student_group) user.save()

create_user会自动做密码哈希,这是Django很重要的安全底线。不要为了省事用objects.create,那会把密码以明文存进数据库,论文答辩时问一句“密码安全怎么保障”就能让你卡壳。

3.3 核心模型和视图的示例实现

创建模型时,我附上一个考勤记录模型作为样板:

from django.db import models from django.contrib.auth.models import User class AttendanceRecord(models.Model): STATUS_CHOICES = ( ("present", "出勤"), ("late", "迟到"), ("leave", "请假"), ("absent", "缺勤"), ) student = models.ForeignKey( "students.Student", on_delete=models.CASCADE, related_name="attendance_records", verbose_name="学生" ) date = models.DateField(verbose_name="日期") status = models.CharField(max_length=10, choices=STATUS_CHOICES, verbose_name="考勤状态") remark = models.TextField(blank=True, verbose_name="备注") class Meta: unique_together = ("student", "date") verbose_name = "考勤记录" verbose_name_plural = "考勤记录" def __str__(self): return f"{self.student} - {self.date} - {self.get_status_display()}"

unique_together保证了同一个学生同一天只能有一条考勤记录,这是数据完整性的重要约束。如果不加这个约束,系统运行久了必然出现同一天两条重复数据,统计时数字就会翻倍。

视图的话,我用类视图ListView来展示学生列表,并且支持简单搜索:

from django.views.generic import ListView from django.db.models import Q from .models import Student class StudentListView(ListView): model = Student template_name = "students/student_list.html" context_object_name = "students" paginate_by = 20 def get_queryset(self): qs = super().get_queryset() keyword = self.request.GET.get("keyword", "") if keyword: qs = qs.filter( Q(name__icontains=keyword) | Q(student_no__icontains=keyword) ) return qs

然后再补充一个用Django自带CreateView实现的考勤录入,配合登录限权和权限判断,一个能用的功能闭环就出来了。写到这里我真心觉得,Django的通用视图确实是为CRUD服务的神器,如果你还在手写每个视图的if request.POST逻辑,真的可以停下来试试类视图。

4. 开发中容易翻车的地方:时区、表单、路径这些细节

如果你完整走了一遍上面的流程,项目大概率能跑起来。但跑起来只是开始,下面这些坑是我实际开发中踩过的,每一个都耗费了不少时间。把它们写在这里,希望你能直接绕过去。

4.1 时间字段与时区:你以为存的是系统时间,其实是个 UTC 时间

Django项目创建后,settings.py里默认是USE_TZ=True,同时系统设置的是TIME_ZONE = "UTC"。如果我们用DateTimeField存请假开始时间、活动时间,存入数据库时Django会按UTC时间保存,而你在中国,本地时间是东八区。这会导致你在页面上看到的活动时间,其实已经悄悄差了8个小时。

解决办法是手动调整settings.py里的两个配置:

TIME_ZONE = "Asia/Shanghai" USE_TZ = True

如果USE_TZ保持True,Django在使用Django模板渲染时间时,会自动把存储的UTC时间转换成TIME_ZONE指定的时区显示,前提是你存储并且读取时都用的是Django的ORM。最怕的情况是代码里用datetime.now()获取了本地时间再存进去,那就会形成“自以为存了本地时间,实际Django以为它存的是UTC时间”的混乱。建议统一:存时间用timezone.now(),展示时间交给模板的{{ value|date:"Y-m-d H:i" }}过滤器,不要自己在视图里手动格式化后传给模板。

我在处理请假审批功能时,就因为时区没配好,前端页面上明明显示的请假截止时间是上午十点,数据库里却存成了凌晨两点,后台审批列的截止时间看起来全是“昨天”。这个错误如果没改,答辩现场一演示准被看出来。

4.2 表单提交数据校验:别把数据校验全交给前端

学生信息里要填手机号,有些同学图省事,在HTML里写一个required属性就完事了。这么做的问题在于,前端的交验根本不能保证数据的真实性,别人随便填个字母也能提交成功。而且Django是服务端框架,重心应该放在后端校验。

Django的Form组件天然支持数据校验,我用它限制了手机号格式和学号长度:

from django import forms from .models import Student class StudentForm(forms.ModelForm): phone = forms.CharField( max_length=11, validators=[ RegexValidator(r"^1[3-9]\d{9}$", message="请输入正确的手机号") ] ) class Meta: model = Student fields = ["student_no", "name", "gender", "phone", "dormitory", "class_info"]

你可能会问,Model里已经定义了字段长度,为什么还要在Form里再写一遍?因为Model的max_length是数据库层面接受的限制,它能把字符串长度超限这件事兜住,但很多业务规则,比如手机号是不是11位、学号是否符合特定前缀,必须在表单层处理。这样做的好处是,如果用户填了不合法的信息,Django会在页面上渲染表单错误信息,你不必手动拼接报错字符串。

4.3 模板继承、静态文件和反向解析

这是Django新手最容易“能跑但很丑”的地方。很多管理系统源码里的页面是几个孤立的HTML文件,每个页面都重复写着完整的<html><head>。等你做到第七八个页面,你就会崩溃。使用模板继承能彻底解决这个问题:

<!-- base.html --> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>{% block title %}班务管理系统{% endblock %}</title> <link rel="stylesheet" href="{% static 'css/style.css' %}"> </head> <body> <nav>{% block nav %}{% endblock %}</nav> <main> {% block content %}{% endblock %} </main> </body> </html>

子模板只需要写{% extends "base.html" %},然后覆盖{% block content %},工作量直接下降一半。

静态文件路径也值得检查。settings.py 里STATIC_URL = "/static/",开发模式下模板里用{% load static %}引用CSS和图片。源码里经常会出现../static/css/style.css这种相对路径,一旦页面路由改深就失效,你需要让所有静态文件都通过Django的{% static %}标签来解析,这样才能保证路径稳定。

5. 源码、文档、答辩:让毕业设计“不仅跑得起来,还能说得清楚”

很多同学在做毕业设计时有个错觉,以为代码能跑起来,提交一个压缩包,就万事大吉。实际上评审老师看一个项目,第一眼永远是结构和文档,而不是去运行你的代码。源码组织得乱,运行文档写得潦草,哪怕功能全部实现,得分也会大打折扣。

5.1 源码目录这么组织,评审老师一眼就能看懂

一个规范的Django项目目录,应该在解压后的第一层就能让老师看出这是个标准项目。我常用的结构是这个样子:

django-class-manage/ ├── manage.py ├── requirements.txt ├── README.md ├── class_manage/ │ ├── settings.py │ ├── urls.py │ ├── wsgi.py │ └── asgi.py ├── students/ │ ├── models.py │ ├── views.py │ ├── admin.py │ ├── forms.py │ ├── urls.py │ └── migrations/ ├── affairs/ │ ├── models.py │ ├── views.py │ ├── admin.py │ ├── forms.py │ ├── urls.py │ └── migrations/ └── templates/ ├── base.html ├── students/ └── affairs/

第一层放manage.py和项目主配置,再往下是每个业务应用。templates单独放一层,不要塞进某个应用里,因为在毕业设计论文的第三章画系统结构图时需要说明“所有模板统一管理”。我见过一个源码,所有HTML文件散落在每个应用的根目录,看起来特别乱,评审印象会差很多。

如果你拿到的源码里的目录结构不是这个,先别急着运行,自己重新把应用拆开、把模板归位,然后确认一下路由是怎么分发的。这里给你个实用技巧:在class_manage/urls.py里,主URLconf用path("", include("students.urls"))这样的方式把请求分发给各应用,不要把所有路由写在一个文件里,否则管理功能和考勤功能的URL混在一起,改起来很费劲。

5.2 运行文档、依赖管理和演示数据缺一不可

requirements.txt是源码能不能跑起来的第一道关。不管你是用pip freeze生成还是手写,至少要包含Django版本号、pymysql、或其他依赖。但注意,pip freeze出来的依赖很可能把一些无关包也算进去,建议只保留项目真正用到的几个。

README.md里再短也要写清这几件事:

  • Python版本和Django版本;
  • 数据库类型,如果是MySQL,要给出创建数据库的SQL语句;
  • 执行哪些命令来初始化表结构;
  • 是否需要创建超级管理员;
  • 默认管理员账号密码是什么,或者去哪里查看。

其中“演示数据”是被忽视得最多的地方。源码里如果没有数据,老师打开系统看到的是空荡荡的页面,体验非常差。你可以用Django的fixture功能,把一套演示数据导出成json文件:

python manage.py dumpdata students.Student affairs.AttendanceRecord notices.Notice --indent 4 > demo_data.json

别人拿到后只需要执行:

python manage.py loaddata demo_data.json

就能看到三四十个学生、十几天考勤记录、几条通知。这个细节能极大提升源码的使用体验,也让同学可以快速看到你的功能全貌。

5.3 答辩现场演示环节的经验分享

源码能跑、文档清晰了,接下来就是答辩演示。我这里有几条实用建议:

第一,不要只演示“都功能能点开”。答辩时老师最怕看到的就是你从头到尾把增删改查点一遍,然后把界面关掉。你要准备一条业务叙事线。比如“我是班主任,我先登录系统,看到今天有三位同学提交了请假申请;我进入考勤模块,标记今天迟到两名同学;这个时候所有学生就能在他们的页面看到请假审批结果,也能看到今天的考勤通知。”把系统的数据流讲出来,比枚举功能强一百倍。

第二,准备好处理“现场跑不起来”的情况。答辩现场的网络环境、数据库环境都可能存在不确定性。建议提前导出一份SQLite版本的项目,或者专门在本机IP地址上跑一个调试服务器,确保演示的时候不需要额外配置数据库连接。我之前帮同学看一个Django系统,答辩前一天发现自己改过密码导致数据库连不上,连夜改了配置才过关。这种事情一定要提前演练一遍。

第三,数据库里尽量保留“有意义的演示数据”,比如请假理由写“生病就医”、活动名写“五四青年节主题班会”,不要用test1、test2这样的占位数据。这些细节看着小,却能体现你做项目的认真程度。答辩老师只要看到这些,就能判断你是自己完整开发过,还是从网上拿了个半成品硬改。

最后我想再强调一件事:毕业设计源码数字编号只是交易记录,真正决定你成果质量的是自己是否完整理解了这个系统的每个环节。哪怕你的源码是从学习社区下载的,也一定要把项目结构、数据模型、核心代码这三块吃透,做到每一步都能讲出“为什么”。这套班务管理系统在Django的技术栈里不算难,但它足以让你把Django的模型、视图、模板、认证、权限、admin后台这些核心能力证明白,论文和答辩就都有了落脚点。项目跑通不是终点,能把里面的每个选择都解释清楚,才算是这堂计算机毕业设计的真正结课。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询