首页 > 解决方案 > 在测试环境中,Django 模型对象不会加载到 Form 中

问题描述

使用 Django 2.1.3

这里出现一个奇怪的错误;我有一个表单多项选择字段,它从数据库中模型中存在的值中提取其选择。

class ChartForm(Form):
    P_CHOICES = tuple((p["p"], p["p"]) for p in VAR.objects.all().values("p"))

    p = MultipleChoiceField(widget=CheckboxSelectMultiple, choices=P_CHOICES, initial=P_CHOICES[0][1])

我正在尝试为项目中的不同应用程序运行测试。它抛出以下错误:

  File "/code/pyyc/forms.py", line 31, in ChartForm
    p = MultipleChoiceField(widget=CheckboxSelectMultiple, choices=P_CHOICES, initial=P_CHOICES[0][1])
IndexError: tuple index out of range

我认为这只是因为没有加载模型对象。所以我从 VAR 应用程序中添加了固定装置。

然而,它仍然抛出错误。大概是在编译测试数据库之前渲染表单......?

所以我现在正在编辑表单,以便手动完成 P_CHOICES,但这显然不适合测试环境。

有人遇到过这个吗?是否有一个聪明的技巧,它不涉及每次你想测试时在表单中注释掉行?

标签: djangotesting

解决方案


我认为你的假设是正确的。类级别属性P_CHOICES是在 Python 第一次加载ChartForm类时创建的,在测试实际开始运行之前。固定装置稍后作为测试的一部分安装setUpClass()(由测试框架调用),但到那时P_CHOICES已经定义并且是空的。

您可以尝试创建MultipleChoiceField没有其choicesinitial属性的 ,然后__init__在数据可用时将它们设置在表单中。例如:

class ChartForm(Form):
    p = MultipleChoiceField(widget=CheckboxSelectMultiple)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        p_choices = tuple((p["p"], p["p"]) for p in VAR.objects.all().values("p"))
        # Now we have the data we can set the attributes
        self.fields['p'].choices = p_choices
        self.fields['p'].initial = p_choices[0][1]

推荐阅读