Django在线测验系统二次启动后问题列表无法恢复的故障排查请求
帮你搞定Django测验重复触发错误的问题
嘿,我一眼就看出问题出在哪了——你在TakeQuizView里定义的questions是类属性,这意味着所有访问这个视图的请求都会共享同一个列表!
问题根源详解
当第一个用户完成测验后,self.questions里的元素已经被remove清空了。第二次再启动测验时,这个类属性还是空的,所以调用self.questions.remove(question)就会触发list.remove(x): x not in list错误。
你尝试添加的if index==1: self.questions=list(Question.objects.all())之所以没用,是因为类属性是全局共享的:如果有多个用户同时测验,或者你在测验过程中刷新页面,这个列表的状态会被打乱,甚至在第二步就被意外清空。
正确解决方案:用Session存储用户独立的测验状态
每个用户的测验进度应该是独立的,我们可以用Django的Session来存储每个用户的问题序列,这样就不会互相干扰了。修改后的代码如下:
urls.py(保持不变)
path('start',views.startquiz,name='start'), path('test/<int:pk>/<int:index>',views.TakeQuizView.as_view(),name='test'),
views.py(重写核心逻辑)
def startquiz(request): # 获取所有问题ID,随机打乱顺序 question_ids = list(Question.objects.values_list('id', flat=True)) random.shuffle(question_ids) # 将打乱后的ID列表存入当前用户的session request.session['question_ids'] = question_ids if question_ids: # 跳转到第一个问题 first_pk = question_ids[0] return redirect(reverse('quiz:test', args=(first_pk, 1))) else: # 没有问题时直接返回主页 return redirect(reverse('quiz:main')) class TakeQuizView(LoginRequiredMixin, View): def get(self, request, pk, index): # 从session获取当前用户的问题ID列表 question_ids = request.session.get('question_ids', []) if not question_ids: # 没有测验数据时返回主页 return redirect(reverse('quiz:main')) try: question = Question.objects.get(id=pk) except Question.DoesNotExist: return redirect(reverse('quiz:main')) ctx = { 'question': question, 'index': index, 'n': len(question_ids) } return render(request, 'quiz/test.html', ctx) def post(self, request, pk, index): question_ids = request.session.get('question_ids', []) if not question_ids: return redirect(reverse('quiz:main')) total_questions = len(question_ids) # 移除当前已展示的问题ID if pk in question_ids: question_ids.remove(pk) request.session['question_ids'] = question_ids # 判断是否还有下一个问题 if index < total_questions: if question_ids: next_pk = question_ids[0] return redirect(reverse('quiz:test', args=(next_pk, index + 1))) else: return redirect(reverse('quiz:main')) else: # 测验结束,清空session里的测验数据 del request.session['question_ids'] return redirect(reverse('quiz:main'))
方案优势
- 用户状态独立:每个用户的测验进度存在自己的Session中,不会和其他用户互相干扰
- 避免重复移除错误:即使刷新页面,Session里的状态会保留,不会重复执行
remove操作 - 逻辑更健壮:处理了没有问题、问题不存在等异常场景
内容的提问来源于stack exchange,提问作者Appre7
相关产品推荐
相关产品推荐

