[Fixed]-Django alter form data in clean method


The correct way to deal with this is by using the field specific clean methods.

Whatever you return from the clean_FOO method is what the cleaned_data will be populated with by the time it gets to the clean function.

Do the following instead:

def clean_subject(self):
        data = self.cleaned_data.get('subject', '')
        if not data:
             raise forms.ValidationError("You must enter a subject")
             # if you don't want this functionality, just remove it.

        if not data.endswith('--help'):
             return data += '--help'
        return data


So, I found this recently having googled about possibly the same problem, whereby in a ModelForm instance of a form, I was trying to edit the data post-validation to provide a suggestion for the end user as to something that would be a valid response (computed from another value they enter into the form).


If you are dealing with a ModelForm descendent specifically, there are two things that are important:

  1. You must call super(YourModelFormClass, self).clean() so that unique fields are checked.
  2. If you are editing cleaned_data, you must also edit the same field on the instance of your model which is attached to your ModelForm:

    def clean(self)
      self.cleaned_data = super(MyModelFormClass, self).clean()
      self.cleaned_data['name']='My suggested value'
      self.instance.name = 'My suggested value'
      return self.cleaned_data

Documentation source for this behaviour


Contrary to the documentation, I have just found that this does not work. you have to edit the form’s self.data in order to get the changes to show up when the form displays.


I think your problem is that you have called self.cleaned_data.get['subject'], and then used it as an array later on.

I have this code for a messaging app that replaces an empty subject with ‘No Subject’

def clean(self):
    super(forms.ModelForm, self).clean()
    subject = self.cleaned_data['subject']
    if subject.isspace():
        self.cleaned_data['subject'] = 'No Subject'
    return self.cleaned_data

For your code, this should work.

def clean(self):
    super(forms.Form, self).clean() #I would always do this for forms.
    subject = self.cleaned_data['subject']
    if not subject.endswith('--help'):
        subject += '--help'
        self.cleaned_data['subject'] = subject
    return self.cleaned_data


“This method should return the cleaned value obtained from cleaned_data, regardless of whether it changed anything or not.” from https://docs.djangoproject.com/en/dev/ref/forms/validation/

Leave a comment