You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django创建ExamGrade时更新StudentCourses的show字段报错求助

Django模型关联更新错误:'RelatedManager' object has no attribute 'show'

问题场景

在Django项目中定义了StudentCourses、ExamGrade、Students等模型,需求是创建ExamGrade记录时,将关联的StudentCourses模型的show布尔字段更新为True,但执行代码时出现错误:'RelatedManager' object has no attribute 'show'。

模型代码(models.py)

class StudentCourses(models.Model):
   id = models.AutoField(primary_key=True)
   student = models.ForeignKey(Students, related_name='studentcourses')
   studentcourse = models.ForeignKey(Courses, related_name='studentcourses', null=True)
   show = models.BooleanField(default=False)

class ExamGrade(models.Model):
    id = models.AutoField(primary_key=True)
    lecturer = models.ForeignKey(Lecturers, null=True, related_name='examgrades')
    student = models.ForeignKey(StudentCourses, related_name='examgrades')

class Students(models.Model):
   id = models.AutoField(primary_key=True)
   admin = models.OneToOneField(CustomUser, on_delete=models.CASCADE, related_name="students")
   profile_pic = models.ImageField(default='default.jpg', upload_to='uploads/student')
   middle_name = models.CharField(max_length=255)
   gender = models.CharField(max_length=255)
   status = models.CharField(max_length=255, null=True)
   country = models.CharField(max_length=255, default=None, null=True, blank=True)
   state = models.CharField(max_length=255, default=None, null=True, blank=True)
   local = models.CharField(max_length=255, default=None, null=True, blank=True)
   school = models.ForeignKey(School, null=True, on_delete=models.CASCADE)
   dob = models.CharField(max_length=100, default=None, blank=True, null=True)
   guardian_name = models.CharField(max_length=11, null=True)
   mobile = models.CharField(max_length=12, null=True, default=None)
   faculty = models.ForeignKey(Faculty, null=True, blank=True, on_delete=models.CASCADE)
   department = models.ForeignKey(Department, null=True, blank=True, on_delete=models.CASCADE)
   level = models.ForeignKey(Level, null=True, blank=True, on_delete=models.CASCADE)
   semester = models.ForeignKey('Semester', null=True, blank=True, on_delete=models.CASCADE)
   session = models.ForeignKey(SessionYearModel, null=True, blank=True, on_delete=models.CASCADE)
   created_at = models.DateTimeField(auto_now_add=True)
   updated_at = models.DateTimeField(auto_now_add=True)

   @property
   def examgrades(self):
      return self.examgrades_set.all().order_by('student')

   @property
   def studentcourses(self):
      return self.studentcourses_set.all().order_by('studentcourse')

视图代码(Views.py)

class CreateGradeView(View):
  def get(self, request, *args, **kwargs):
    lecturer= Lecturers.objects.get(admin=request.user)
    course = LecturerCourse.objects.filter(lecturer=lecturer)
    context = {
        'course':course,
        'room_name': "broadcast"
        }
    return render(request, 'superadmin/lecturer/add-grade.html',context)

  def post(self, request, *args, **kwargs):
    lecturer = request.POST.get('lecturer')
    lecturer = Lecturers.objects.get(admin=lecturer)
    student = request.POST.get('student')
    student = StudentCourses.objects.get(id=student)
    course = request.POST.get('lecturercourse')
    course = LecturerCourse.objects.get(id=course)
    ca_1 = request.POST.get('ca_1')
    ca_2 = request.POST.get('ca_2')
    ca_3 = request.POST.get('ca_3')
    exam = request.POST.get('exam')

    if ExamGrade.objects.filter(lecturer=lecturer, student=student, lecturercourse=course, status=True).exists():
        messages.warning(request, "User Exam Score already marked")
        return redirect('emisapp:add-grade')
    
    try:
        examgrades = ExamGrade(lecturer=lecturer, student=student, lecturercourse=course, ca_1=ca_1,ca_2=ca_2,ca_3=ca_3,exam=exam, status=True)
        print(examgrades.student.show) 
        examgrades.student.show = True
        print(examgrades.student.show) 
        examgrades.save()
        messages.success(request, 'Weldone you just saved Exam Score for the day')
        return redirect('emisapp:add-grade')
    except:
        messages.error(request, 'There is an saving to database')
        return redirect('emisapp:add-grade')

AJAX代码(ajax.py)

def load_student_for_attendance_by_courses(request):
  studentcourse = request.GET.get('studentcourse')
  student = StudentCourses.objects.filter(studentcourse=studentcourse, 
  show=False).order_by('student')
  return render(request, 'superadmin/settings/load-student-dropdown.html', {'student':student})

模板代码(load-student-dropdown.html)

<option value="">--Select a Student--</option>
{% for s in student %}
<option value="{{s.id}}">{{ s.student.admin.username }} - {{ s.student.admin.last_name }} {{ s.student.middle_name }} {{ s.student.admin.first_name }}</option>
{% endfor %}

错误原因

  1. 重名冲突:Students模型中定义的@property方法(examgrades、studentcourses)与Django自动生成的反向关联管理器重名,导致模型关联访问逻辑混乱,出现将RelatedManager(查询集管理器)当成单个实例访问属性的情况。
  2. 未单独保存关联实例:修改StudentCourses的show字段后,仅保存了ExamGrade实例,未对StudentCourses实例执行保存操作,即使逻辑正确也无法持久化修改。

修复方案

1. 重命名冲突的@property方法

修改Students模型中的@property方法名,避免覆盖Django自动生成的反向关联管理器:

class Students(models.Model):
   # 其他字段保持不变

   @property
   def related_examgrades(self):
      return self.examgrades.all().order_by('student')

   @property
   def related_studentcourses(self):
      return self.studentcourses.all().order_by('studentcourse')

2. 正确保存关联实例

修改视图中post方法的try块,单独保存StudentCourses实例:

try:
    # 先保存ExamGrade实例
    examgrades = ExamGrade(lecturer=lecturer, student=student, lecturercourse=course, ca_1=ca_1,ca_2=ca_2,ca_3=ca_3,exam=exam, status=True)
    examgrades.save()
    
    # 更新并保存StudentCourses实例
    student.show = True
    student.save()
    
    messages.success(request, '已成功保存考试成绩')
    return redirect('emisapp:add-grade')
except Exception as e:
    messages.error(request, f'保存失败:{str(e)}')
    return redirect('emisapp:add-grade')

3. 优化字段名(可选)

为避免模型关联混淆,建议修改ExamGrade的student字段名为student_course,明确关联的是StudentCourses实例:

class ExamGrade(models.Model):
    id = models.AutoField(primary_key=True)
    lecturer = models.ForeignKey(Lecturers, null=True, related_name='examgrades', on_delete=models.SET_NULL)
    student_course = models.ForeignKey(StudentCourses, related_name='examgrades', on_delete=models.CASCADE)
    # 其他字段保持不变

对应视图代码同步修改:

examgrades = ExamGrade(lecturer=lecturer, student_course=student, lecturercourse=course, ca_1=ca_1,ca_2=ca_2,ca_3=ca_3,exam=exam, status=True)

内容的提问来源于stack exchange,提问作者Deji Peter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 05:50:28