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:
- You must call
super(YourModelFormClass, self).clean()
so that unique fields are checked. 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/
精彩评论