From eb0751a4c0b2d5e248ff3babc37a4764b102e25a Mon Sep 17 00:00:00 2001 From: Joseph Kocherhans Date: Mon, 22 Feb 2010 23:06:09 +0000 Subject: [PATCH] =?UTF-8?q?Fixed=20#12901.=20Exclude=20overridden=20form?= =?UTF-8?q?=20fields=20from=20model=20field=20validation.=20Thanks,=20Honz?= =?UTF-8?q?a=20Kr=C3=A1l.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://code.djangoproject.com/svn/django/trunk@12496 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/forms/models.py | 24 +++++++++++++++++++++--- tests/modeltests/model_forms/tests.py | 21 +++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 tests/modeltests/model_forms/tests.py diff --git a/django/forms/models.py b/django/forms/models.py index 0039516f47..e292c1b9a7 100644 --- a/django/forms/models.py +++ b/django/forms/models.py @@ -276,10 +276,18 @@ class BaseModelForm(BaseForm): # adding these values to the model after form validation. if field not in self.fields: exclude.append(f.name) + + # Don't perform model validation on fields that were defined + # manually on the form and excluded via the ModelForm's Meta + # class. See #12901. + elif self._meta.fields and field not in self._meta.fields: + exclude.append(f.name) + # Exclude fields that failed form validation. There's no need for # the model fields to validate them as well. elif field in self._errors.keys(): exclude.append(f.name) + # Exclude empty fields that are not required by the form. The # underlying model field may be required, so this keeps the model # field from raising that error. @@ -719,16 +727,26 @@ class BaseInlineFormSet(BaseModelFormSet): def add_fields(self, form, index): super(BaseInlineFormSet, self).add_fields(form, index) if self._pk_field == self.fk: - form.fields[self._pk_field.name] = InlineForeignKeyField(self.instance, pk_field=True) + name = self._pk_field.name + kwargs = {'pk_field': True} else: # The foreign key field might not be on the form, so we poke at the # Model field to get the label, since we need that for error messages. + name = self.fk.name kwargs = { - 'label': getattr(form.fields.get(self.fk.name), 'label', capfirst(self.fk.verbose_name)) + 'label': getattr(form.fields.get(name), 'label', capfirst(self.fk.verbose_name)) } if self.fk.rel.field_name != self.fk.rel.to._meta.pk.name: kwargs['to_field'] = self.fk.rel.field_name - form.fields[self.fk.name] = InlineForeignKeyField(self.instance, **kwargs) + + form.fields[name] = InlineForeignKeyField(self.instance, **kwargs) + + # Add the generated field to form._meta.fields if it's defined to make + # sure validation isn't skipped on that field. + if form._meta.fields: + if isinstance(form._meta.fields, tuple): + form._meta.fields = list(form._meta.fields) + form._meta.fields.append(self.fk.name) def get_unique_error_message(self, unique_check): unique_check = [field for field in unique_check if field != self.fk.name] diff --git a/tests/modeltests/model_forms/tests.py b/tests/modeltests/model_forms/tests.py new file mode 100644 index 0000000000..49ea314bc6 --- /dev/null +++ b/tests/modeltests/model_forms/tests.py @@ -0,0 +1,21 @@ +from django.test import TestCase +from django import forms +from models import Category + + +class IncompleteCategoryForm(forms.ModelForm): + """ + A form that replaces the model's url field with a custom one. This should + prevent the model field's validation from being called. + """ + url = forms.CharField(required=False) + + class Meta: + fields = ('name', 'slug') + model = Category + +class ValidationTest(TestCase): + def test_validates_with_replaced_field(self): + form = IncompleteCategoryForm(data={'name': 'some name', 'slug': 'some-slug'}) + assert form.is_valid() +