如何用Django forms实现考试问题与对应单选答案的动态渲染
实现方案
1. 动态构造考试表单类
因为不同考试的题目数量、选项内容都是动态变化的,所以我们需要根据当前考试实例动态生成表单类,代码如下:
from django import forms from .models import ExamAnswer def get_exam_form(exam): # 拉取当前考试的所有问题,可根据需要调整排序规则 questions = exam.questions.all() class ExamForm(forms.Form): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 遍历每个问题,动态添加单选字段 for question in questions: # 构造选项列表:格式为(答案ID, 答案文本),提交后可直接通过答案ID判分 choices = [(ans.id, ans.text) for ans in question.answers.all()] # 字段名用前缀+问题ID的格式,方便后续识别对应问题 self.fields[f"q_{question.id}"] = forms.ChoiceField( label=question.text, choices=choices, widget=forms.RadioSelect, required=True ) return ExamForm
2. 视图调用逻辑
视图中先获取对应考试实例,再生成对应的表单类,处理提交逻辑:
from django.shortcuts import render, get_object_or_404 from .models import Exam def exam_page(request, exam_id): exam = get_object_or_404(Exam, id=exam_id) # 生成当前考试专属的表单类 ExamForm = get_exam_form(exam) if request.method == "POST": form = ExamForm(request.POST) if form.is_valid(): # 判分逻辑示例 total = exam.questions.count() correct_count = 0 for field_name, selected_ans_id in form.cleaned_data.items(): q_id = int(field_name.split("_")[-1]) # 取当前问题的正确答案ID right_ans = ExamAnswer.objects.get(question_id=q_id, is_correct=True) if int(selected_ans_id) == right_ans.id: correct_count += 1 final_score = round(correct_count / total * 100, 2) # 后续可自行添加存分、判断是否通过的逻辑 return render(request, "exam_result.html", {"score": final_score}) else: form = ExamForm() return render(request, "exam_page.html", {"form": form})
3. 模板渲染代码(exam_page.html)
渲染出来的结构和你预期的完全一致:
<form method="post"> {% csrf_token %} {% for field in form %} <div> {{ field.label }}<br> {% for option in field %} {{ option.tag }} {{ option.choice_label }}<br> {% endfor %} </div> {% endfor %} <div> <input type="submit" value="提交考试"> </div> </form>
说明:表单会自动给同个问题的单选按钮设置相同的name属性,保证每个问题只能选一个选项,不需要额外手动处理分组逻辑。
内容的提问来源于stack exchange,提问作者Matthew Tomsho
相关产品推荐
相关产品推荐

