Fixed #25349 -- Allowed a ModelForm to unset a fields with blank=True, required=False.
This commit is contained in:
parent
5c31d8d189
commit
375e1cfe2b
|
@ -376,11 +376,6 @@ class BaseModelForm(BaseForm):
|
||||||
|
|
||||||
exclude = self._get_validation_exclusions()
|
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
|
# Foreign Keys being used to represent inline relationships
|
||||||
# are excluded from basic field value validation. This is for two
|
# are excluded from basic field value validation. This is for two
|
||||||
# reasons: firstly, the value may not be supplied (#12507; the
|
# reasons: firstly, the value may not be supplied (#12507; the
|
||||||
|
@ -392,6 +387,11 @@ class BaseModelForm(BaseForm):
|
||||||
if isinstance(field, InlineForeignKeyField):
|
if isinstance(field, InlineForeignKeyField):
|
||||||
exclude.append(name)
|
exclude.append(name)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.instance = construct_instance(self, self.instance, opts.fields, opts.exclude)
|
||||||
|
except ValidationError as e:
|
||||||
|
self._update_errors(e)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.instance.full_clean(exclude=exclude, validate_unique=False)
|
self.instance.full_clean(exclude=exclude, validate_unique=False)
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
|
|
|
@ -474,3 +474,9 @@ class StrictAssignmentAll(models.Model):
|
||||||
if self._should_error is True:
|
if self._should_error is True:
|
||||||
raise ValidationError(message="Cannot set attribute", code='invalid')
|
raise ValidationError(message="Cannot set attribute", code='invalid')
|
||||||
super(StrictAssignmentAll, self).__setattr__(key, value)
|
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)
|
||||||
|
|
|
@ -23,7 +23,7 @@ from django.utils import six
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Article, ArticleStatus, Author, Author1, BetterWriter, BigInt, Book,
|
Article, ArticleStatus, Author, Author1, Award, BetterWriter, BigInt, Book,
|
||||||
Category, Character, Colour, ColourfulItem, CommaSeparatedInteger,
|
Category, Character, Colour, ColourfulItem, CommaSeparatedInteger,
|
||||||
CustomErrorMessage, CustomFF, CustomFieldForExclusionModel, DateTimePost,
|
CustomErrorMessage, CustomFF, CustomFieldForExclusionModel, DateTimePost,
|
||||||
DerivedBook, DerivedPost, Document, ExplicitPK, FilePathModel,
|
DerivedBook, DerivedPost, Document, ExplicitPK, FilePathModel,
|
||||||
|
@ -236,6 +236,40 @@ class ModelFormBaseTest(TestCase):
|
||||||
obj = f2.save()
|
obj = f2.save()
|
||||||
self.assertEqual(obj.character, char)
|
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):
|
def test_missing_fields_attribute(self):
|
||||||
message = (
|
message = (
|
||||||
"Creating a ModelForm without either the 'fields' attribute "
|
"Creating a ModelForm without either the 'fields' attribute "
|
||||||
|
|
Loading…
Reference in New Issue