Fixed #28387 -- Fixed has_changed() for disabled form fields that subclass it.
This commit is contained in:
parent
2e9ada1551
commit
5debbdfcc8
|
@ -586,6 +586,8 @@ class FileField(Field):
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def has_changed(self, initial, data):
|
def has_changed(self, initial, data):
|
||||||
|
if self.disabled:
|
||||||
|
return False
|
||||||
if data is None:
|
if data is None:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
@ -706,6 +708,8 @@ class BooleanField(Field):
|
||||||
raise ValidationError(self.error_messages['required'], code='required')
|
raise ValidationError(self.error_messages['required'], code='required')
|
||||||
|
|
||||||
def has_changed(self, initial, data):
|
def has_changed(self, initial, data):
|
||||||
|
if self.disabled:
|
||||||
|
return False
|
||||||
# Sometimes data or initial may be a string equivalent of a boolean
|
# Sometimes data or initial may be a string equivalent of a boolean
|
||||||
# so we should run it through to_python first to get a boolean value
|
# so we should run it through to_python first to get a boolean value
|
||||||
return self.to_python(initial) != self.to_python(data)
|
return self.to_python(initial) != self.to_python(data)
|
||||||
|
@ -864,6 +868,8 @@ class MultipleChoiceField(ChoiceField):
|
||||||
)
|
)
|
||||||
|
|
||||||
def has_changed(self, initial, data):
|
def has_changed(self, initial, data):
|
||||||
|
if self.disabled:
|
||||||
|
return False
|
||||||
if initial is None:
|
if initial is None:
|
||||||
initial = []
|
initial = []
|
||||||
if data is None:
|
if data is None:
|
||||||
|
@ -1042,6 +1048,8 @@ class MultiValueField(Field):
|
||||||
raise NotImplementedError('Subclasses must implement this method.')
|
raise NotImplementedError('Subclasses must implement this method.')
|
||||||
|
|
||||||
def has_changed(self, initial, data):
|
def has_changed(self, initial, data):
|
||||||
|
if self.disabled:
|
||||||
|
return False
|
||||||
if initial is None:
|
if initial is None:
|
||||||
initial = ['' for x in range(0, len(data))]
|
initial = ['' for x in range(0, len(data))]
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1250,6 +1250,8 @@ class ModelChoiceField(ChoiceField):
|
||||||
return Field.validate(self, value)
|
return Field.validate(self, value)
|
||||||
|
|
||||||
def has_changed(self, initial, data):
|
def has_changed(self, initial, data):
|
||||||
|
if self.disabled:
|
||||||
|
return False
|
||||||
initial_value = initial if initial is not None else ''
|
initial_value = initial if initial is not None else ''
|
||||||
data_value = data if data is not None else ''
|
data_value = data if data is not None else ''
|
||||||
return str(self.prepare_value(initial_value)) != str(data_value)
|
return str(self.prepare_value(initial_value)) != str(data_value)
|
||||||
|
@ -1334,6 +1336,8 @@ class ModelMultipleChoiceField(ModelChoiceField):
|
||||||
return super().prepare_value(value)
|
return super().prepare_value(value)
|
||||||
|
|
||||||
def has_changed(self, initial, data):
|
def has_changed(self, initial, data):
|
||||||
|
if self.disabled:
|
||||||
|
return False
|
||||||
if initial is None:
|
if initial is None:
|
||||||
initial = []
|
initial = []
|
||||||
if data is None:
|
if data is None:
|
||||||
|
|
|
@ -21,3 +21,7 @@ Bugfixes
|
||||||
|
|
||||||
* Fixed crash in ``runserver``'s ``autoreload`` with Python 2 on Windows with
|
* Fixed crash in ``runserver``'s ``autoreload`` with Python 2 on Windows with
|
||||||
non-``str`` environment variables (:ticket:`28174`).
|
non-``str`` environment variables (:ticket:`28174`).
|
||||||
|
|
||||||
|
* Corrected ``Field.has_changed()`` to return ``False`` for disabled form
|
||||||
|
fields: ``BooleanField``, ``MultipleChoiceField``, ``MultiValueField``,
|
||||||
|
``FileField``, ``ModelChoiceField``, and ``ModelMultipleChoiceField``.
|
||||||
|
|
|
@ -57,3 +57,7 @@ class BooleanFieldTest(SimpleTestCase):
|
||||||
self.assertFalse(f.has_changed(True, 'True'))
|
self.assertFalse(f.has_changed(True, 'True'))
|
||||||
self.assertTrue(f.has_changed(False, 'True'))
|
self.assertTrue(f.has_changed(False, 'True'))
|
||||||
self.assertTrue(f.has_changed(True, 'False'))
|
self.assertTrue(f.has_changed(True, 'False'))
|
||||||
|
|
||||||
|
def test_disabled_has_changed(self):
|
||||||
|
f = BooleanField(disabled=True)
|
||||||
|
self.assertIs(f.has_changed('True', 'False'), False)
|
||||||
|
|
|
@ -74,5 +74,9 @@ class FileFieldTest(SimpleTestCase):
|
||||||
# with here)
|
# with here)
|
||||||
self.assertTrue(f.has_changed('resume.txt', {'filename': 'resume.txt', 'content': 'My resume'}))
|
self.assertTrue(f.has_changed('resume.txt', {'filename': 'resume.txt', 'content': 'My resume'}))
|
||||||
|
|
||||||
|
def test_disabled_has_changed(self):
|
||||||
|
f = FileField(disabled=True)
|
||||||
|
self.assertIs(f.has_changed('x', 'y'), False)
|
||||||
|
|
||||||
def test_file_picklable(self):
|
def test_file_picklable(self):
|
||||||
self.assertIsInstance(pickle.loads(pickle.dumps(FileField())), FileField)
|
self.assertIsInstance(pickle.loads(pickle.dumps(FileField())), FileField)
|
||||||
|
|
|
@ -68,3 +68,7 @@ class MultipleChoiceFieldTest(SimpleTestCase):
|
||||||
self.assertFalse(f.has_changed([2, 1], ['1', '2']))
|
self.assertFalse(f.has_changed([2, 1], ['1', '2']))
|
||||||
self.assertTrue(f.has_changed([1, 2], ['1']))
|
self.assertTrue(f.has_changed([1, 2], ['1']))
|
||||||
self.assertTrue(f.has_changed([1, 2], ['1', '3']))
|
self.assertTrue(f.has_changed([1, 2], ['1', '3']))
|
||||||
|
|
||||||
|
def test_disabled_has_changed(self):
|
||||||
|
f = MultipleChoiceField(choices=[('1', 'One'), ('2', 'Two')], disabled=True)
|
||||||
|
self.assertIs(f.has_changed('x', 'y'), False)
|
||||||
|
|
|
@ -103,6 +103,10 @@ class MultiValueFieldTest(SimpleTestCase):
|
||||||
['some text', ['J', 'P'], ['2009-04-25', '11:44:00']],
|
['some text', ['J', 'P'], ['2009-04-25', '11:44:00']],
|
||||||
))
|
))
|
||||||
|
|
||||||
|
def test_disabled_has_changed(self):
|
||||||
|
f = MultiValueField(fields=(CharField(), CharField()), disabled=True)
|
||||||
|
self.assertIs(f.has_changed(['x', 'x'], ['y', 'y']), False)
|
||||||
|
|
||||||
def test_form_as_table(self):
|
def test_form_as_table(self):
|
||||||
form = ComplexFieldForm()
|
form = ComplexFieldForm()
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
|
|
|
@ -1702,6 +1702,10 @@ class ModelChoiceFieldTests(TestCase):
|
||||||
['Select a valid choice. That choice is not one of the available choices.']
|
['Select a valid choice. That choice is not one of the available choices.']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_disabled_modelchoicefield_has_changed(self):
|
||||||
|
field = forms.ModelChoiceField(Author.objects.all(), disabled=True)
|
||||||
|
self.assertIs(field.has_changed('x', 'y'), False)
|
||||||
|
|
||||||
def test_disabled_multiplemodelchoicefield(self):
|
def test_disabled_multiplemodelchoicefield(self):
|
||||||
class ArticleForm(forms.ModelForm):
|
class ArticleForm(forms.ModelForm):
|
||||||
categories = forms.ModelMultipleChoiceField(Category.objects.all(), required=False)
|
categories = forms.ModelMultipleChoiceField(Category.objects.all(), required=False)
|
||||||
|
@ -1727,6 +1731,10 @@ class ModelChoiceFieldTests(TestCase):
|
||||||
self.assertEqual(form.errors, {})
|
self.assertEqual(form.errors, {})
|
||||||
self.assertEqual([x.pk for x in form.cleaned_data['categories']], [category1.pk])
|
self.assertEqual([x.pk for x in form.cleaned_data['categories']], [category1.pk])
|
||||||
|
|
||||||
|
def test_disabled_modelmultiplechoicefield_has_changed(self):
|
||||||
|
field = forms.ModelMultipleChoiceField(Author.objects.all(), disabled=True)
|
||||||
|
self.assertIs(field.has_changed('x', 'y'), False)
|
||||||
|
|
||||||
def test_modelchoicefield_iterator(self):
|
def test_modelchoicefield_iterator(self):
|
||||||
"""
|
"""
|
||||||
Iterator defaults to ModelChoiceIterator and can be overridden with
|
Iterator defaults to ModelChoiceIterator and can be overridden with
|
||||||
|
|
Loading…
Reference in New Issue