Rob
Rob

Reputation: 637

Returning cleaned_data when overwriting clean() method in Django Model forms

I need to overwrite the clean() method in a Django Model form to perform additional uniqueness checks on the data entered.

This page gives implementation details: https://docs.djangoproject.com/en/1.11/ref/forms/validation/ Copied here:

 def clean(self):
    cleaned_data = super(ContactForm, self).clean()
    cc_myself = cleaned_data.get("cc_myself")
    subject = cleaned_data.get("subject")

    if cc_myself and subject:
        # Only do something if both fields are valid so far.
        if "help" not in subject:
            raise forms.ValidationError(
                "Did not send for 'help' in the subject despite "
                "CC'ing yourself."
            )

However I'm confused why this method doesn't return cleaned_data at the end of the function? Surely that is the correct thing to do?

Upvotes: 9

Views: 5196

Answers (3)

Quique
Quique

Reputation: 956

In Django < 1.7, form.clean() was required to return a dictionary of cleaned_data.
This method may still return a dictionary of data to be used, but it’s no longer required.

Upvotes: 0

CoffeeBasedLifeform
CoffeeBasedLifeform

Reputation: 2921

Have a look at django's _clean_form method:

def _clean_form(self):
    try:
        cleaned_data = self.clean()
    except ValidationError as e:
        self.add_error(None, e)
    else:
        if cleaned_data is not None:
            self.cleaned_data = cleaned_data

Read the last bullet point on the forms doc and especially this bit of the ModelForm doc.

If the clean method raises a ValidationError, the error gets added to the forms' errors. If the clean method has returned anything and threw no errors, the form is going to use that for its cleaned_data attribute. Otherwise it will keep its 'old' one.

In your case, all that your clean method does, is validating an aspect of the form.

Upvotes: 8

scharette
scharette

Reputation: 9977

The example you are interested in is an override of the clean method for related fields. This means that it validates a logic that implicate more than one field. Consider this as the form's clean method. Thus, you don't want to return any values in this case.

As the doc says :

"Be careful when doing this in practice, since it can lead to confusing form output. We’re showing what is possible here and leaving it up to you and your designers to work out what works effectively in your particular situation."

It depends on your particular case, but in my experience with overriding clean on one particular field, you'll want to return it if the validation passes. Again, this is for only one field.

Here's another example from the doc, but for one field validation:

def clean_recipients(self):
    data = self.cleaned_data['recipients']
    if "[email protected]" not in data:
        raise forms.ValidationError("You have forgotten about Fred!")

    # Always return a value to use as the new cleaned data, even if
    # this method didn't change it.
    return data

Upvotes: 0

Related Questions