diff --git a/django/forms/models.py b/django/forms/models.py index 13aea4acab..869138c922 100644 --- a/django/forms/models.py +++ b/django/forms/models.py @@ -292,13 +292,16 @@ class BaseModelForm(BaseForm): 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. + # Exclude empty fields that are not required by the form, if the + # underlying model field is required. This keeps the model field + # from raising a required error. Note: don't exclude the field from + # validaton if the model field allows blanks. If it does, the blank + # value may be included in a unique check, so cannot be excluded + # from validation. else: form_field = self.fields[field] field_value = self.cleaned_data.get(field, None) - if field_value is None and not form_field.required: + if not f.blank and not form_field.required and field_value in EMPTY_VALUES: exclude.append(f.name) return exclude diff --git a/tests/modeltests/model_forms/mforms.py b/tests/modeltests/model_forms/mforms.py index 5777b4cb6e..aef763ef62 100755 --- a/tests/modeltests/model_forms/mforms.py +++ b/tests/modeltests/model_forms/mforms.py @@ -1,6 +1,7 @@ +from django import forms from django.forms import ModelForm -from models import Product, Price, Book, DerivedBook, ExplicitPK, Post, DerivedPost +from models import Product, Price, Book, DerivedBook, ExplicitPK, Post, DerivedPost, Writer class ProductForm(ModelForm): class Meta: @@ -30,3 +31,9 @@ class PostForm(ModelForm): class DerivedPostForm(ModelForm): class Meta: model = DerivedPost + +class CustomWriterForm(ModelForm): + name = forms.CharField(required=False) + + class Meta: + model = Writer diff --git a/tests/modeltests/model_forms/tests.py b/tests/modeltests/model_forms/tests.py index fb4e8adb45..6a5f9395cc 100644 --- a/tests/modeltests/model_forms/tests.py +++ b/tests/modeltests/model_forms/tests.py @@ -2,7 +2,8 @@ import datetime from django.test import TestCase from django import forms from models import Category, Writer, Book, DerivedBook, Post -from mforms import ProductForm, PriceForm, BookForm, DerivedBookForm, ExplicitPKForm, PostForm, DerivedPostForm +from mforms import (ProductForm, PriceForm, BookForm, DerivedBookForm, + ExplicitPKForm, PostForm, DerivedPostForm, CustomWriterForm) class IncompleteCategoryFormWithFields(forms.ModelForm): @@ -37,6 +38,10 @@ class ValidationTest(TestCase): form = IncompleteCategoryFormWithExclude(data={'name': 'some name', 'slug': 'some-slug'}) assert form.is_valid() + def test_notrequired_overrides_notblank(self): + form = CustomWriterForm({}) + assert form.is_valid() + # unique/unique_together validation class UniqueTest(TestCase): def setUp(self):