pirr
pirr

Reputation: 495

django model form clean method with foreign key

I try override clean method for model form with foreign key.

Model:

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

Form:

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

In the test I get an error:

KeyError: 'name'.

If I remove self.cleaned_data['name'] from msg - I do not get self.cleaned_data['doc_type'].

Where I'm wrong?

Upvotes: 2

Views: 6009

Answers (1)

Shang Wang
Shang Wang

Reputation: 25559

You can't cross reference other fields in clean_foo methods, because not all fields' clean_foo methods are called when you are in one of them. There might be some values of the form that are not populated yet, so clean_name() is not yet called when you call clean_doc_type(), thus you don't have self.cleaned_data['name'].

This should be done in clean method. Django doc very explicitly documented this:

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.

Also, your clean method doesn't make much sense and not necessary at all. You wouldn't able to choose a foreignkey that doesn't exist in ModelForm. Even if you force the front end to do so, the field would auto fail the validation and give error:

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

Upvotes: 5

Related Questions