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

Django Form动态传递Choice选项提交时报无效选择错误如何解决

报错根因
  • 表单校验时的可选选项和你提交的选项所属题目不匹配:
    你在get_context_data方法里提前将全局计数变量count+1,当用户提交上一道题的答案时,POST请求触发表单实例化,get_form_kwargs获取的是count自增后下一道题的选项列表,上一道题的选项id自然不在当前校验用的可选列表里,触发校验失败。
  • 额外隐患:你使用类变量存储题目集合、计数count,多用户同时访问时数据会互相覆盖,存在严重的逻辑错误。
  • 小问题:你自定义的表单字段名为answerss,但在form_valid里获取值的时候写的是answers,拼写错误会拿不到提交的id值。
修复步骤
  1. 调整计数变量的更新逻辑,不要在get_context_data里提前自增,改为提交表单成功后再更新计数,同时把类变量改为存在用户session里,避免多用户串数据:
# 先删掉类里定义的question_collection、question_id_collection、count类变量
def get_context_data(self,*args,**kwargs) :
    context = super().get_context_data(*args,**kwargs)
    # 从session取当前计数,默认是0
    current_count = self.request.session.get('quiz_count', 0)
    # 初始化题目集合到session,避免每次请求都查库
    if 'question_id_collection' not in self.request.session:
        find = quizz.objects.get(category=formality.question_subject)
        ids = question.objects.filter(quiz_id = find.quiz_id)
        self.request.session['question_id_collection'] = [i.question_id.hex for i in ids]
        self.request.session['question_collection'] = [i.question for i in ids]
    question_id_collection = self.request.session['question_id_collection']
    question_collection = self.request.session['question_collection']
    
    context['data4'] = correctAnswer.objects.filter(question_id = question_id_collection[current_count])
    context['data5'] = question.objects.filter(question = question_collection[current_count]).values('question_id')
    context['data6'] = correctAnswer.objects.filter(check_answer_bool = 1, question_id = question_collection[current_count]).values('correct_Answer_id')
    context['data2'] = current_count
    context['data3'] = question_collection[current_count]
    return context

def get_form_kwargs(self, *args,**kwargs) :
    message = super(Start_Game,self).get_form_kwargs(*args,**kwargs)
    current_count = self.request.session.get('quiz_count', 0)
    question_id_collection = self.request.session['question_id_collection']
    option_choice = []
    q = correctAnswer.objects.filter(question_id = question_id_collection[current_count]).values_list('correct_Answer_id','answer')
    for item in q:
        option_choice.append((item[0].hex,item[1]))
    message['options'] = option_choice      
    return  message

def form_valid(self, form) :
    current_count = self.request.session.get('quiz_count', 0)
    question_id_collection = self.request.session['question_id_collection']
    question_collection = self.request.session['question_collection']
    # 字段名是answerss,同时MultipleChoiceField提交的是数组,要用getlist
    print('selected id is ',self.request.POST.getlist('answerss'))
    obj = form.save(commit= False)
    obj.user_id = self.request.user
    # 外键赋值要传实例或者直接给_id传值,不能传values查询集
    obj.question_id = question.objects.get(question = question_collection[current_count])
    obj.correct_Answer_id = correctAnswer.objects.get(check_answer_bool = 1, question_id = question_id_collection[current_count])
    obj.save()
    # 提交成功再更新计数
    current_count +=1
    if current_count >= len(question_id_collection):
        current_count = 0
    self.request.session['quiz_count'] = current_count
    return super().form_valid(form)
  1. 如果你不需要校验answerss字段的选项合法性,可以直接给字段加required=False或者在校验前动态更新choices,不过更推荐上面调整计数逻辑的方案,符合业务流程。

内容的提问来源于stack exchange,提问作者Divit Rao

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 09:15:03