Ticket #12596: 12596-simple.diff

File 12596-simple.diff, 3.4 KB (added by Honza_Kral, 6 years ago)

Simpler variant of the patch that only goes half way

  • 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): 
    263263        # changed from the initial data, short circuit any validation.
    264264        if self.empty_permitted and not self.has_changed():
    265265            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):
    266274        for name, field in self.fields.items():
    267275            # value_from_datadict() gets the data from the data dictionaries.
    268276            # Each widget type knows how to retrieve its own data, because some
    class BaseForm(StrAndUnicode): 
    282290                self._errors[name] = self.error_class(e.messages)
    283291                if name in self.cleaned_data:
    284292                    del self.cleaned_data[name]
     293
     294    def _clean_form(self):
    285295        try:
    286296            self.cleaned_data = self.clean()
    287297        except ValidationError, e:
    288298            self._errors[NON_FIELD_ERRORS] = self.error_class(e.messages)
    289         if self._errors:
    290             delattr(self, 'cleaned_data')
    291299
    292300    def clean(self):
    293301        """
  • django/forms/models.py

    diff --git a/django/forms/models.py b/django/forms/models.py
    index cce2319..6aa08f7 100644
    a b class BaseModelForm(BaseForm): 
    280280                    exclude.append(f.name)
    281281        return exclude
    282282
    283     def clean(self):
     283    def _clean_form(self):
     284        # construct the instance after the form has been validated on the form level.
     285        # this is a partial fix for #12596 which allows people to still use
     286        # ModelForms without calling super().clean() even though they thus
     287        # loose some validation (everything run on models, including validating
     288        # the fields)
    284289        opts = self._meta
    285290        self.instance = construct_instance(self, self.instance, opts.fields, opts.exclude)
     291        super(BaseModelForm, self)._clean_form()
     292
     293    def clean(self):
    286294        exclude = self._get_validation_exclusions()
    287295        try:
    288296            self.instance.full_clean(exclude=exclude)
  • 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): 
    5050        form = TripleForm({'left': '1', 'middle': '3', 'right': '1'})
    5151        self.failUnless(form.is_valid())
    5252
     53class 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
     62class 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
    5374class FPForm(forms.ModelForm):
    5475    class Meta:
    5576        model = FilePathModel
Back to Top