开发者

django alter form data in clean method

开发者 https://www.devze.com 2023-02-16 02:10 出处:网络
I have a django form that I want to custom clean.Instead of just specifying an error message like here (Django form and field validation), I\'d like to just alter the field myself.I tried severl ways,

I have a django form that I want to custom clean. Instead of just specifying an error message like here (Django form and field validation), I'd like to just alter the field myself. I tried severl ways, but keep running into error like cleaned_data is immutable.

So to solve this I made a copy, changed it and reassigned it to self. Is this the best way to do this? Could/should I have handled this in the view? Making a copy seems poor form but I keep running into 'immutabl开发者_运维技巧e' road blocks. Sample code below where I simply check if the subject has '--help' at the end, and if not add it. Thanks

def clean(self):
        cleaned_data=self.cleaned_data.copy()
        subject=cleaned_data.get['subject']
        if not subject.endswith('--help'):
            cleaned_data['subject']=subject+='--help'
        self.cleaned_data=cleaned_data
        return self.cleaned_data


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


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


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).

TL;DR

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

EDIT:

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.


"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/

0

精彩评论

暂无评论...
验证码 换一张
取 消