Ticket #12596: 12596.diff
File 12596.diff, 5.9 KB (added by , 15 years ago) |
---|
-
django/forms/forms.py
diff --git a/django/forms/forms.py b/django/forms/forms.py index c53a901..73599d0 100644
a b class BaseForm(StrAndUnicode): 263 263 # changed from the initial data, short circuit any validation. 264 264 if self.empty_permitted and not self.has_changed(): 265 265 return 266 267 self._clean_fields() 268 self._clean_form() 269 270 if self._errors: 271 delattr(self, 'cleaned_data') 272 273 def _clean_fields(self): 266 274 for name, field in self.fields.items(): 267 275 # value_from_datadict() gets the data from the data dictionaries. 268 276 # Each widget type knows how to retrieve its own data, because some … … class BaseForm(StrAndUnicode): 282 290 self._errors[name] = self.error_class(e.messages) 283 291 if name in self.cleaned_data: 284 292 del self.cleaned_data[name] 293 294 def _clean_form(self): 285 295 try: 286 296 self.cleaned_data = self.clean() 287 297 except ValidationError, e: 288 298 self._errors[NON_FIELD_ERRORS] = self.error_class(e.messages) 289 if self._errors:290 delattr(self, 'cleaned_data')291 299 292 300 def clean(self): 293 301 """ -
django/forms/models.py
diff --git a/django/forms/models.py b/django/forms/models.py index cce2319..3ac1854 100644
a b class BaseModelForm(BaseForm): 250 250 super(BaseModelForm, self).__init__(data, files, auto_id, prefix, object_data, 251 251 error_class, label_suffix, empty_permitted) 252 252 253 254 253 def _get_validation_exclusions(self): 255 254 """ 256 255 For backwards-compatibility, several types of fields need to be … … class BaseModelForm(BaseForm): 280 279 exclude.append(f.name) 281 280 return exclude 282 281 283 def clean(self): 282 def _clean_fields(self): 283 """ 284 Cleans the form fields, constructs the instance, then cleans the model 285 fields. 286 """ 287 super(BaseModelForm, self)._clean_fields() 284 288 opts = self._meta 285 289 self.instance = construct_instance(self, self.instance, opts.fields, opts.exclude) 286 290 exclude = self._get_validation_exclusions() 287 291 try: 288 self.instance. full_clean(exclude=exclude)292 self.instance.clean_fields(exclude=exclude) 289 293 except ValidationError, e: 290 for k, v in e.message_dict.items(): 291 if k != NON_FIELD_ERRORS: 292 self._errors.setdefault(k, ErrorList()).extend(v) 293 # Remove the data from the cleaned_data dict since it was invalid 294 if k in self.cleaned_data: 295 del self.cleaned_data[k] 296 if NON_FIELD_ERRORS in e.message_dict: 297 raise ValidationError(e.message_dict[NON_FIELD_ERRORS]) 294 self._populate_errors(e.message_dict) 295 296 def _clean_form(self): 297 """ 298 Runs the instance's clean method, then the form's. This is becuase the 299 form will run validate_unique() by default, and we should run the 300 model's clean method first. 301 """ 302 exclude = self._get_validation_exclusions() 303 try: 304 self.instance.clean() 305 except ValidationError, e: 306 self._populate_errors(e.message_dict) 307 super(BaseModelForm, self)._clean_form() 308 309 def _populate_errors(self, message_dict): 310 """ 311 Updates self._errors with the errors from a ValidationError's 312 message_dict attribute. 313 """ 314 for k, v in message_dict.items(): 315 if k != NON_FIELD_ERRORS: 316 self._errors.setdefault(k, ErrorList()).extend(v) 317 # Remove the data from the cleaned_data dict since it was invalid 318 if k in self.cleaned_data: 319 del self.cleaned_data[k] 320 if NON_FIELD_ERRORS in message_dict: 321 messages = message_dict[NON_FIELD_ERRORS] 322 self._errors.setdefault(NON_FIELD_ERRORS, ErrorList()).extend(messages) 323 324 def clean(self): 325 self.validate_unique() 298 326 return self.cleaned_data 299 327 328 def validate_unique(self): 329 exclude = self._get_validation_exclusions() 330 for name in self._errors.keys(): 331 if name != NON_FIELD_ERRORS and name not in exclude: 332 exclude.append(name) 333 try: 334 self.instance.validate_unique(exclude=exclude) 335 except ValidationError, e: 336 self._populate_errors(e.message_dict) 337 300 338 def save(self, commit=True): 301 339 """ 302 340 Saves this ``form``'s cleaned_data into model instance -
tests/regressiontests/model_forms_regress/tests.py
diff --git a/tests/regressiontests/model_forms_regress/tests.py b/tests/regressiontests/model_forms_regress/tests.py index f8b6511..57d5655 100644
a b class UniqueTogetherTests(TestCase): 50 50 form = TripleForm({'left': '1', 'middle': '3', 'right': '1'}) 51 51 self.failUnless(form.is_valid()) 52 52 53 class TripleFormWithCleanOverride(forms.ModelForm): 54 class Meta: 55 model = Triple 56 57 def clean(self): 58 if not self.cleaned_data['left'] == self.cleaned_data['right']: 59 raise forms.ValidationError('Left and right should be equal') 60 return self.cleaned_data 61 62 class OverrideCleanTests(TestCase): 63 def test_override_clean(self): 64 """ 65 Regression for #12596: Calling super from ModelForm.clean() should be 66 optional. 67 """ 68 form = TripleFormWithCleanOverride({'left': 1, 'middle': 2, 'right': 1}) 69 self.failUnless(form.is_valid()) 70 # form.instance.left will be None if the instance was not constructed 71 # by form.full_clean(). 72 self.assertEquals(form.instance.left, 1) 73 53 74 class FPForm(forms.ModelForm): 54 75 class Meta: 55 76 model = FilePathModel