Django 表单验证:如何设置“必填”条件?

15 投票
2 回答
17168 浏览
提问于 2025-04-15 19:32

我刚开始学习Django(还有Python),现在想弄明白怎么根据条件来验证表单的某些内容。在这个情况下,有一个HTML界面,用户可以从一些小工具中选择日期和时间。表单对象上的clean方法会把时间和日期字段的值转换成datetime格式。

除了这个HTML界面,还有一个iPhone客户端可以调用这个应用程序,我想传入一个类似UNIX时间戳的时间值。

我的表单代码是这样的:

class FooForm(forms.ModelForm):
    foo_date             = forms.CharField(required=True, widget=forms.RadioSelect(choices=DATE_CHOICES))
    foo_time             = forms.CharField(required=True, widget=SelectTimeWidget())
    foo_timestamp        = forms.CharField(required=False)

我该怎么做才能让foo_datefoo_time变成必填项,除非提供了foo_timestamp呢?

2 个回答

10

我发现自己需要一个“标准”的方法来处理这个问题,因为我的表单里有几个字段是根据条件来决定是否必填的。所以我创建了一个父类,并在里面写了以下这个方法:

def validate_required_field(self, cleaned_data, field_name, message="This field is required"):
    if(field_name in cleaned_data and cleaned_data[field_name] is None):
        self._errors[field_name] = self.error_class([message])
        del cleaned_data[field_name]

然后在我表单的清理方法里,我有:

def clean(self):
    cleaned_data = super(FormClass, self).clean()
    if(condition):
        self.validate_required_field(cleaned_data, 'field_name')

到目前为止,这个方法对我来说运作得非常好。

30

这个操作是通过表单上的 clean 方法来完成的。不过,你需要把 foo_datefoo_time 设置为 required=False,因为 clean 方法只有在每个字段都经过验证后才会被调用(具体可以参考文档)。

class FooForm(forms.Form)
    # your field definitions

    def clean(self):
        data = self.cleaned_data
        if data.get('foo_timestamp', None) or (data.get('foo_date', None) and data.get('foo_time', None)):
            return data
        else:
            raise forms.ValidationError('Provide either a date and time or a timestamp')

撰写回答