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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 11:09:04