毕业设计:学校管理系统评分模块预填与更新问题求助
学校管理系统成绩模块问题及解决方案
问题描述
我正在开发毕业设计项目——学校管理系统,在实现成绩模块时卡壳3周,目前功能接近预期:可根据选定科目在页面列出所有学生,教师能在学生姓名旁输入成绩。但存在两个核心问题:
- 输入框未预填数据库中已有的学生成绩
- 针对同一学生、同一科目、同一季度及学年输入成绩时,系统会创建新的成绩对象而非更新已有记录
效果对比
当前输出:
预期输出:
现有代码
视图代码
def add_gradebook_for(request, id): global student, s current_year = AcademicYear.objects.get(active=True) current_quarter = Quarter.objects.get(active=True) if request.method == 'GET': subjects = Subject.objects.filter(faculty_id=request.user.id) subject = Subject.objects.get(pk=id) students = Students.objects.filter(section__subject_section__in=[subject]) context = { "subjects": subjects, "subject": subject, "students": students, } return render(request, 'grading/add_gradebook_for.html', context) if request.method == 'POST': ids = () data = request.POST.copy() data.pop('csrfmiddlewaretoken', None) subject = Subject.objects.get(pk=id) for key in data.keys(): ids = ids + (str(key),) for s in range(0, len(ids)): student = Students.objects.get(id=ids[s]) score = data.getlist(ids[s]) total_grade = score[0] obj = Students.objects.get(id=ids[s]) obj.total_grade = total_grade try: a = Gradebook.objects.get(student=student, subject=subject, total_grade=total_grade, academic_year=current_year, quarter=current_quarter) a.total_grade = total_grade a.subject = subject a.save() except: Gradebook.objects.update_or_create(student=student, subject=subject, total_grade=total_grade, academic_year=current_year, quarter=current_quarter) messages.success(request, "Grades Successfully Recorded!") return HttpResponseRedirect(reverse_lazy('add_gradebook_for', kwargs={'id': id}))
HTML模板(省略无关部分)
<div class="card-body"> <div id="table" class="table-editable"> <table class="table table-bordered table-responsive-md table-striped text-center"> <tr> <th class="text-center">Student</th> <th class="text-center">Grade</th> </tr> {% for student in students %} <tr> <td class="pt-3-half" name="{{ student.id }}"> {{ student.first_Name }} {{ student.last_Name }} </td> <td class="pt-3-half"> <input id="total_grade" class="score" type="number" name="{{ student.id }}" value="{{ student.total_grade }}"> </td> </tr> {% endfor %} </table> </div> </div>
模型(省略无关字段)
class Gradebook(models.Model): subject = models.ForeignKey(Subject, on_delete=models.CASCADE) student = models.ForeignKey(Students, on_delete=models.CASCADE) total_grade = models.FloatField(blank=True, null=True, default=0, max_length=5) academic_year = models.ForeignKey(AcademicYear, on_delete=models.CASCADE) quarter = models.ForeignKey(Quarter, on_delete=models.CASCADE) class Subject(models.Model): section = models.ForeignKey(Section, on_delete=models.CASCADE) name = models.CharField(max_length=255) faculty = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.CASCADE) class Section(models.Model): level = models.ForeignKey(Level, null=True, on_delete=models.CASCADE) section = models.CharField(max_length=15) class Students(models.Model): name = models.CharField(max_length=50) section = models.ForeignKey(Section, on_delete=models.CASCADE)
问题解决
1. 输入框预填已有成绩
问题根源
模板中调用student.total_grade,但Students模型并未定义该字段,实际成绩存储在Gradebook模型中,关联条件为学生、科目、当前学年和季度。
修复步骤
- 修改视图GET逻辑:为每个学生查询对应科目的当前成绩,存入字典传递到模板
if request.method == 'GET': subjects = Subject.objects.filter(faculty_id=request.user.id) subject = Subject.objects.get(pk=id) students = Students.objects.filter(section__subject_section__in=[subject]) # 构建学生ID到成绩的映射 student_grades = {} for student in students: try: grade_record = Gradebook.objects.get( student=student, subject=subject, academic_year=current_year, quarter=current_quarter ) student_grades[student.id] = grade_record.total_grade except Gradebook.DoesNotExist: student_grades[student.id] = 0 # 无成绩时显示默认值0 context = { "subjects": subjects, "subject": subject, "students": students, "student_grades": student_grades, } return render(request, 'grading/add_gradebook_for.html', context)
- 添加模板过滤器:在app目录下创建
templatetags/grade_filters.py,实现字典取值过滤器
from django import template register = template.Library() @register.filter def get_item(dictionary, key): return dictionary.get(key, 0)
- 修改模板:加载过滤器并更新输入框的value值
{% load grade_filters %} <!-- 省略其他代码 --> <input id="total_grade" class="score" type="number" name="{{ student.id }}" value="{{ student_grades|get_item:student.id }}">
2. 避免重复创建成绩对象
问题根源
update_or_create的查询参数包含total_grade,导致成绩变化时系统判定为新对象;同时try块中查询已有记录也错误地将total_grade作为条件,无法匹配到原有记录。
修复步骤
- 简化并修正POST逻辑:以学生、科目、学年、季度为唯一标识,使用
update_or_create直接更新或创建记录,删除无用的Students对象操作
if request.method == 'POST': data = request.POST.copy() data.pop('csrfmiddlewaretoken', None) subject = Subject.objects.get(pk=id) # 遍历所有提交的学生成绩 for student_id, score in data.items(): student = Students.objects.get(id=student_id) total_grade = float(score) # 按唯一条件更新或创建成绩记录 Gradebook.objects.update_or_create( student=student, subject=subject, academic_year=current_year, quarter=current_quarter, defaults={'total_grade': total_grade} ) messages.success(request, "成绩已成功记录!") return HttpResponseRedirect(reverse_lazy('add_gradebook_for', kwargs={'id': id}))
内容的提问来源于stack exchange,提问作者CORSICANA
相关产品推荐
相关产品推荐

