使用 Django 构建成绩管理模块(Scores)
在前面的章节中,我们已经完成了学生管理和老师管理模块。 如果你已经理解了老师管理模块的实现方式,那么接下来的成绩管理,你会发现——几乎是同一套模式的复用。
在这一节中,我们将一起实现一个完整的 成绩管理模块(scores),并重点关注它与老师管理模块之间的异同。
1.成绩管理模块的功能概览
在正式开始编码之前,我们先快速看一下成绩管理模块需要实现哪些功能:
- 成绩列表展示
- 按班级 / 关键字搜索
- 新增成绩
- 修改成绩
- 删除成绩
- 批量删除
- 查看成绩详情
- 批量导入 / 导出成绩
可以看到,这些功能大部分都和老师管理模块完全一致,不同点主要体现在业务校验逻辑上。
2.URL 设计(scores/urls.py)
为了单独管理成绩的URL, 同样的在config/urls.py全局路由中配置:
# 代码位置:config/urls.py
from accounts import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', RedirectView.as_view(url='/students/', permanent=False)),
path('grades/', include('grades.urls')),
path('students/', include('students.urls')),
path('teachers/', include('teachers.urls')),
path('scores/', include('scores.urls')),
path('my_scores', MyScoreListView.as_view(), name='my_scores'),
]
接下来,在scores应用下创建一个urls.py文件。我们首先从 URL 配置开始,代码如下:
# 代码位置:scores/urls.py
from django.urls import path
from .views import upload_scores, export_scores, ScoreListView, ScoreCreateView, ScoreUpdateView, ScoreDeleteView,ScoreDeleteMultipleView, ScoreDetailView, MyScoreListView, StatisticsView
urlpatterns = [
path('', ScoreListView.as_view(), name='score_list'),
path('create/', ScoreCreateView.as_view(), name='score_create'),
path('update/<int:pk>/', ScoreUpdateView.as_view(), name='score_update'),
path('delete/<int:pk>/', ScoreDeleteView.as_view(), name='score_delete'),
path('delete_multiple/', ScoreDeleteMultipleView.as_view(), name='score_delete_multiple'),
path('detail/<int:pk>/', ScoreDetailView.as_view(), name='score_detail'),
path('upload_scores/', upload_scores, name="upload_scores"),
path('export_scores/', export_scores, name='export_scores'),
path('my_scores', MyScoreListView.as_view(), name='my_scores'),
path('statistics/', StatisticsView.as_view(), name='statistics'),
]
📌 设计思路
- 列表 / 新增 / 修改 / 删除使用 类视图(CBV)
- 批量导入 / 导出使用 函数视图
- 个人成绩和统计页面单独拆分
这种 URL 结构在大型项目中非常常见,可维护性也更好。
3.成绩模型设计(models.py)
接下来是数据模型。
在 models.py 中创建 Teacher 模型。
核心字段设计
成绩表包含以下信息:
- 考试名称
- 学号
- 姓名
- 语文成绩
- 数学成绩
- 英语成绩
成绩与班级的关系
这里有一个业务约束:
一个班级有多个成绩
因此:
- Score 与 Grade:一对多关系
在scores/models.py文件中,添加如下代码:
from django.db import models
from students.models import Grade
# Create your models here.
class Score(models.Model):
title = models.CharField(max_length=20,help_text='title/考试名称',verbose_name='考试名称')
student_number = models.CharField(max_length=20,verbose_name='学号')
student_name = models.CharField(max_length=20,help_text='name/姓名',verbose_name='姓名')
chinese_score = models.DecimalField(max_digits=5,decimal_places=2,help_text='score/语文分数',verbose_name='语文分数')
math_score = models.DecimalField(max_digits=5,decimal_places=2,help_text='score/数学分数',verbose_name='数学分数')
english_score = models.DecimalField(max_digits=5,decimal_places=2,help_text='score/英语分数',verbose_name='英语分数')
# 班级表一对多关联
grade = models.ForeignKey(Grade, on_delete=models.CASCADE, related_name='score', verbose_name='班级')
def __str__(self) -> str:
return self.title
class Meta:
db_table = "score"
verbose_name_plural = "成绩信息"
verbose_name = "成绩信息"
为什么不直接关联 Student?
这是一个很好的思考点。
在实际业务中,成绩往往是考试快照数据:
- 即使学生以后改名
- 即使学生转班
历史成绩也不应该发生变化
因此我们选择在成绩表中 冗余存储学生姓名和学号,而不是直接 ForeignKey 到 Student。
继续阅读完整内容
以上为免费预览。前往「Django + Vue 全栈课程」,查看后续完整讲解、案例演示和配套资料。
查看课程详情