Django筛选学生已选课程测验触发QuerySet精确查询报错
报错原因
触发The QuerySet value for an exact lookup must be limited to one result using slicing.的核心原因是筛选Quiz时错误地将多结果的QuerySet作为精确匹配的参数传入:
- 你查询得到的
user_course是包含多条UserCourse记录的结果集,不是单个课程实例/课程ID - Django的精确筛选(
字段名=值语法)仅支持匹配单个值,直接传入多结果QuerySet就会抛出该错误
另外代码里还有一个隐藏bug:Course模型的__str__方法返回self.title,但模型中实际定义的标题字段是course_title,后续调用课程实例的字符串表示时会触发属性不存在的错误。
修复方案
1. 修正Course模型的__str__方法
修改models.py中Course类的魔法方法:
class Course(models.Model): course_creator = models.ForeignKey(User, on_delete=models.CASCADE, related_name="quiz_user") course_title = models.CharField(max_length=255) slug = models.SlugField(unique=True) # 模板中用到了course_thumbnail字段,若未定义请补充,参考如下: # course_thumbnail = models.ImageField(upload_to="course/thumbnails/", null=True, blank=True) def __str__(self): # 修正字段名匹配错误 return self.course_title
2. 修正视图层筛选逻辑
使用__in筛选器匹配多个课程ID,同时可以通过select_related提前联表查询关联的课程数据,减少模板渲染时的重复数据库查询:
def StudentQuizList(request): # 获取当前用户有效报名的课程ID列表,若不需要校验支付状态可删除payment_status过滤条件 enrolled_course_ids = UserCourse.objects.filter( user=request.user, payment_status="paid" ).values_list("course_id", flat=True) # 筛选所有属于已报名课程的测验 quizzes = Quiz.objects.filter( course_id__in=enrolled_course_ids ).select_related("course") context = { "quizzes": quizzes, } return render(request, 'student_dashboard/quiz.html', context)
3. 模板小问题修复
quiz.html中课程标题的a标签缺少等号,修正为:
<h3 class="card-title"><a href="#">{{quiz.course.course_title|title|truncatechars:30}}</a></h3>
逻辑说明
values_list('course_id', flat=True)会直接从UserCourse表中取出所有关联的课程ID,组成纯ID列表,避免加载不必要的字段数据course_id__in筛选器会匹配所有course_id在已报名课程ID列表中的Quiz记录,符合「仅展示学生已报名课程对应测验」的需求select_related('course')会在查询Quiz时一次性联表查询关联的Course数据,避免循环渲染测验时每次都单独查一次课程信息,大幅提升查询效率
内容的提问来源于stack exchange,提问作者Destiny Franks
相关产品推荐
相关产品推荐

