Fixed #25349 -- Allowed a ModelForm to unset a fields with blank=True, required=False.

This commit is contained in:
haxoza 2015-11-14 17:38:27 +01:00 committed by Tim Graham
parent 5c31d8d189
commit 375e1cfe2b
3 changed files with 46 additions and 6 deletions

View File

@ -376,11 +376,6 @@ class BaseModelForm(BaseForm):
exclude = self._get_validation_exclusions()
try:
self.instance = construct_instance(self, self.instance, opts.fields, exclude)
except ValidationError as e:
self._update_errors(e)
# Foreign Keys being used to represent inline relationships
# are excluded from basic field value validation. This is for two
# reasons: firstly, the value may not be supplied (#12507; the
@ -392,6 +387,11 @@ class BaseModelForm(BaseForm):
if isinstance(field, InlineForeignKeyField):
exclude.append(name)
try:
self.instance = construct_instance(self, self.instance, opts.fields, opts.exclude)
except ValidationError as e:
self._update_errors(e)
try:
self.instance.full_clean(exclude=exclude, validate_unique=False)
except ValidationError as e:

View File

@ -474,3 +474,9 @@ class StrictAssignmentAll(models.Model):
if self._should_error is True:
raise ValidationError(message="Cannot set attribute", code='invalid')
super(StrictAssignmentAll, self).__setattr__(key, value)
# A model with ForeignKey(blank=False, null=True)
class Award(models.Model):
name = models.CharField(max_length=30)
character = models.ForeignKey(Character, models.SET_NULL, blank=False, null=True)

View File

@ -23,7 +23,7 @@ from django.utils import six
from django.utils._os import upath
from .models import (
Article, ArticleStatus, Author, Author1, BetterWriter, BigInt, Book,
Article, ArticleStatus, Author, Author1, Award, BetterWriter, BigInt, Book,
Category, Character, Colour, ColourfulItem, CommaSeparatedInteger,
CustomErrorMessage, CustomFF, CustomFieldForExclusionModel, DateTimePost,
DerivedBook, DerivedPost, Document, ExplicitPK, FilePathModel,
@ -236,6 +236,40 @@ class ModelFormBaseTest(TestCase):
obj = f2.save()
self.assertEqual(obj.character, char)
def test_blank_false_with_null_true_foreign_key_field(self):
"""
A ModelForm with a model having ForeignKey(blank=False, null=True)
and the form field set to required=False should allow the field to be
unset.
"""
class AwardForm(forms.ModelForm):
class Meta:
model = Award
fields = '__all__'
def __init__(self, *args, **kwargs):
super(AwardForm, self).__init__(*args, **kwargs)
self.fields['character'].required = False
character = Character.objects.create(username='user', last_action=datetime.datetime.today())
award = Award.objects.create(name='Best sprinter', character=character)
data = {'name': 'Best tester', 'character': ''} # remove character
form = AwardForm(data=data, instance=award)
self.assertTrue(form.is_valid())
award = form.save()
self.assertIsNone(award.character)
def test_save_blank_false_with_required_false(self):
"""
A ModelForm with a model with a field set to blank=False and the form
field set to required=False should allow the field to be unset.
"""
obj = Writer.objects.create(name='test')
form = CustomWriterForm(data={'name': ''}, instance=obj)
self.assertTrue(form.is_valid())
obj = form.save()
self.assertEqual(obj.name, '')
def test_missing_fields_attribute(self):
message = (
"Creating a ModelForm without either the 'fields' attribute "