Django验证错误未被引发;cleaned_data中不存在密钥

brvekthn  于 2023-03-04  发布在  Go
关注(0)|答案(1)|浏览(125)

我在ModelForm子类上有以下表单域:

    • 表单. py**
class ProjectUpdateForm(ModelForm):

    start_date = DateField(...)
    due_date = DateField(label="Due Date",
                         required=True,
                         widget=CustomDatePicker(),
                         validators=[validate_not_past])

    def clean(self):
        super().clean()    # Problem: this isn't this raising a ValidationError...
        start_date = self.cleaned_data.get('start_date')
        due_date = self.cleaned_data.get('due_date')
        if start_date > due_date:          # ...instead getting a TypeError from this line!
            raise ValidationError("Project Start Date cannot be after Project End Date")
    • 验证器. py**
def validate_not_past(value):
    today = datetime.date.today()
    if value and value < today:
        raise ValidationError('This date cannot be in the past.', code='invalid')

每当我输入过去的日期时,应用程序都会抛出一个TypeError: '>' not supported between instances of 'datetime.date' and 'NoneType'(请参阅上面的注解以了解清楚)。
尝试进行故障排除后,POST数据从表单中正常返回。出现问题的原因是run_validators()按预期引发了由validate_not_past验证器(如上所述)触发的ValidationError。但是,self.cleaned_data字典没有得到due_date键,而不是引发ValidationError

    • 我不明白为什么没有引发ValidationError。我在其他地方找不到捕获它的代码。**

先谢了。

lp0sw83n

lp0sw83n1#

理想情况下,clean_method可以选择返回一个字典(推荐)来返回cleaned_data。如果您这样做,并且在Forms中进行继承,您将不会遇到任何错误。当前,您的ProjectUpdateForm没有正确使用它来调用超类上的clean()方法。如果您按如下方式正确调用它,您的代码将得到修复:

class ProjectUpdateForm(ModelForm):

    start_date = DateField(...)
    due_date = DateField(label="Due Date",
                         required=True,
                         widget=CustomDatePicker(),
                         validators=[validate_not_past])

    def clean(self):
        cleaned_data = super().clean()
        start_date = cleaned_data.get('start_date')
        due_date = cleaned_data.get('due_date')
        if start_date and due_date and start_date > due_date:
            raise ValidationError("Project Start Date cannot be after Project End Date")
        return cleaned_data

注意,在比较start_datedue_date之前,我还检查了它们是否为None。如果start_date也是强制的,那么从代码中看不出来,所以我添加了这个额外的检查。
最后,我还返回了cleaned_data,这是可选的,但推荐使用,因为这样就可以使这个表单在其他表单中继承,而不必担心从超类表单中正确传播错误。

相关问题