不需要基于另一个字段值的字段

Don't require field based on another field's value

我有一个 Django ModelForm,我希望其中一个字段被视为有条件地需要。我希望它默认是必需的,但不是必需的,具体取决于另一个字段的值。我的模型看起来类似于:

class MyModel(models.Model):
    foo = models.BooleanField()
    bar = models.CharField(choices=(('A', 'A'),('B', 'B'),('C', 'C')),)

都没有 null=Trueblank=True,所以当我呈现我的表单时,它们都显示为 "required",这正是我想要的。

但是,我的表单模板中有一些 javascript 根据 foo 的输入值隐藏了 bar 字段输入。在这种情况下,当提交表单时,我不想出现任何关于 bar 被要求的验证错误。

我正在尝试在我的 ModelForm 的 clean 方法中实现这个逻辑,如下所示:

def clean(self):
    data = super(MyModelForm, self).clean()
    if data.get('foo') == True and 'bar' in self.errors:
        del self.errors['bar']
    return data

然而,这似乎仍然给我一个 "This field cannot be blank." 错误。我注意到我的 ModelForm 也有一个 _errors 字典,但是如果我尝试添加 del self._errors['bar'] 我最终会出现异常。

我找到了一些方法来做与我想要的相反的事情 (1, 2),即默认情况下不需要该字段,然后在 [=17] 中检查在某些情况下它应该是必需的=],但这不是我想要的。

我也曾尝试添加 data['bar'] = " " 作为解决方法,但后来我收到关于未选择其中一个选项的错误。理想情况下,我宁愿只能够保存空字符串。

这里的问题是,除了调用表单的 clean 方法外,form also calls post_clean on the form's instance。因为模型上的字段没有 blank=True,所以在清理模型时会引发另一个错误并将其传递回表单。

要解决,请在模型上设置 blank=True。这具有使该字段在表单上显示为不需要的不良副作用。要在表单上设置必填字段,只需在 init 中设置必填标志:

def __init__(self, *args, **kwargs):
    super(MyForm, self).__init__( *args, **kwargs)
    self.fields['bar'].required = True

除了原始问题中的 clean 方法之外,这足以创建默认需要的条件必填字段,并且根据另一个字段的值不需要。

您可以覆盖 _clean_fields 方法以提供您的条件更改:

def _clean_fields(self):
    if self.data.get('foo', None) == True:
        self.fields['bar'].required = False
    super(MyForm, self)._clean_fields()