django 模型表单清理方法与外键

django model form clean method with foreign key

我尝试使用外键重写模型表单的清理方法。

型号:

class Doc(Model):
   name = CharField()
   doc_type = ForeignKey(DictDocType)

表格:

class DocForm(ModelForm):
           
    class Meta:
        model = Doc
        fields = '__all__'
    
    def clean_doc_type(self)
        doc_type_name = self.cleaned_data['doc_type']
    
        try:
            DictDocType.objects.get(name=doc_type_name)
        except DictDocType.DoesNotExist:
            msg = '{0} does not exist in dictdoc {1}.'.format(
                doc_type_name, self.cleaned_data['name'])
            raise ValidationError(msg)
        return name

在测试中我得到一个错误:

KeyError: 'name'.

如果我从 msg 中删除 self.cleaned_data['name'] - 我不会得到 self.cleaned_data['doc_type']

我哪里错了?

您不能在 clean_foo 方法中交叉引用其他字段,因为当您在其中一个方法中时,并非所有字段的 clean_foo 方法都会被调用。表单的某些值可能尚未填充,因此当您调用 clean_doc_type() 时尚未调用 clean_name(),因此您没有 self.cleaned_data['name'].

这应该在 clean 方法中完成。 Django doc 非常明确地记录了这一点:

By the time the form’s clean() method is called, all the individual field clean methods will have been run (the previous two sections), so self.cleaned_data will be populated with any data that has survived so far. So you also need to remember to allow for the fact that the fields you are wanting to validate might not have survived the initial individual field checks.

此外,您的 clean 方法没有多大意义,也根本没有必要。您将无法选择 ModelForm 中不存在的 foreignkey。即使您强制前端这样做,该字段也会自动验证失败并给出错误:

Select a valid choice. foo is not one of the available choices.