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

Django多题测验:PostgreSQL仅存首个选项,Pytest报302失败

多选项测验数据保存异常问题修复

问题现象

开发多选项测验功能时,PostgreSQL仅保存第一个选项,无论提交多少个选项和正确标记。POST数据显示提交了5个选项(第3、5个为正确),但表单cleaned_data仅返回[{'text': '99', 'is_correct': False}],最终仅该选项入库,同时Pytest测试返回302失败。

核心原因

表单初始化时仅从initial参数读取ans_count生成字段,POST提交时未根据提交的ans_count值动态生成对应数量的answer_*和is_correct_*字段,导致Django忽略了除初始1个字段外的所有动态提交数据。

修复方案

1. 修改forms.py,适配POST提交的ans_count值

在表单的__init__方法中,优先从POST数据读取ans_count,确保生成对应数量的字段:

class AddMultipleForm(forms.ModelForm):
    ans_count = forms.IntegerField(min_value=1, label="Number of Answers Anzahl der Antworten")

    class Meta:
        model = MultiQuesModel
        fields = ["question", "language_name"]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 优先从POST数据取ans_count,没有则用initial或默认1
        ans_count = int(self.data.get("ans_count", self.initial.get("ans_count", 1)))

        for i in range(ans_count):
            self.fields[f"answer_{i}"] = forms.CharField(max_length=200, required=True)
            self.fields[f"is_correct_{i}"] = forms.BooleanField(
                required=False, widget=forms.CheckboxInput(attrs={"class": "checkbox"})
            )

    def clean(self):
        cleaned_data = super().clean()
        ans_count = cleaned_data.get("ans_count")
        print(ans_count)
        answers = []

        for i in range(ans_count):
            answer_text = cleaned_data.get(f"answer_{i}")
            is_correct = cleaned_data.get(f"is_correct_{i}")

            if answer_text:
                answers.append({"text": answer_text, "is_correct": is_correct})

        if not answers:
            raise forms.ValidationError(
                "Please fill out at least one answer. Bitte füllen Sie mindestens eine Antwort aus."
            )

        cleaned_data["answers"] = answers
        return cleaned_data

2. 修复HTML模板中的label错误

在multiformular.html中,修正重复的label标签:

<!-- 原错误代码 -->
{{ form.question.label_tag }} {{ form.language_name }}
<!-- 修改为 -->
{{ form.language_name.label_tag }} {{ form.language_name }}

3. 验证视图逻辑(无需修改,确认即可)

views.py中的保存逻辑正确,确保表单验证通过后,遍历所有answers_data创建或获取Answer实例,并通过through_defaults设置正确标记:

# views.py中post方法的保存逻辑(无需修改)
if form.is_valid():
    instance = form.save(commit=False)
    instance.save()

    answers_data = form.cleaned_data["answers"]
    print(answers_data)
    for answer_data in answers_data:
        answer_text = answer_data["text"]
        is_correct = answer_data["is_correct"]

        answer, _ = Answer.objects.get_or_create(text=answer_text)
        instance.answers.add(answer, through_defaults={"is_correct": is_correct})

    return redirect("success_page")

测试验证

修复后重新提交表单,检查cleaned_data是否包含所有提交的选项数据,确认数据库中正确保存所有选项及对应的is_correct标记,同时Pytest测试应返回正常响应(不再是302失败)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 01:20:56