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

如何编写单元测试验证Django模型表单有效性?解决验证失败问题

问题分析与解决方案

你的测试失败主要有两个核心原因,咱们一步步拆解:

1. 表单初始化时未传入对应Question实例

在QuestionForm的__init__方法里,你是通过self.instance.pk来过滤该问题对应的Option的,但在测试中创建表单时,你只传了data=data,没有传入instance=question_1。这时候self.instance是一个空的Question对象,pk为None,导致Option.objects.filter(question_id=self.instance.pk)返回空集合,表单的selected_option字段根本没有可用选项,自然任何输入都会被判为非法。

2. 测试数据的selected_option值不匹配

你的表单selected_option字段的choices是用Option的主键作为值((f'{option.pk}', f'{option}')),但测试里传的是option_1.option_text,两者完全不匹配,这也会触发"选项不属于可用范围"的错误。


修复后的测试代码

修改test_valid_data函数如下:

def test_valid_data(self):
    # 创建关联的Collection、Question、Option实例
    collection = Collection.objects.create()
    question_1 = Question.objects.create(
        question_text='What is the width of the telephone?',
        date_published=timezone.now(),
        collection=collection
    )
    option_1 = question_1.options.create(
        option_text='Five centimetres'
    )
    # 注意:这里要传入instance=question_1,并且selected_option传option的pk
    data = {
        'question_text': question_1.question_text,
        'selected_option': str(option_1.pk),  # 转成字符串,因为choices里的键是字符串格式
    }
    form = QuestionForm(data=data, instance=question_1)
    self.assertTrue(form.is_valid())

额外优化建议

为了避免后续出现类似问题,你可以在表单的__init__里增加对instance的判断,比如当instance未保存(pk不存在)时,隐藏selected_option字段或者给出提示:

def __init__(self, *args, **kwargs):
    super(QuestionForm, self).__init__(*args, **kwargs)
    if self.instance.pk:  # 只有当Question已经保存到数据库时才加载选项
        self.fields['selected_option'] = forms.ChoiceField(
            choices=[(str(option.pk), str(option)) for option in self.instance.options.all()],
            widget=RadioSelect,
            required=True,
            error_messages={
                'required': 'The question form lacks a selected_option'
            }
        )
    else:
        # 如果是新建Question,可以移除该字段或者设置为非必填
        self.fields.pop('selected_option', None)

这样处理后,表单的行为会更健壮,也能避免在未传入有效instance时出现无选项的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:23:05