Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #23162 -- Renamed forms.Field._has_changed() to has_changed().

  • Loading branch information...
commit deed00c0d803d324a3dfdeba52458b6b009c1a90 1 parent 99561ee
@gmunumel gmunumel authored timgraham committed
View
2  django/contrib/auth/forms.py
@@ -64,7 +64,7 @@ def bound_data(self, data, initial):
# render an input field.
return initial
- def _has_changed(self, initial, data):
+ def has_changed(self, initial, data):
return False
View
2  django/contrib/auth/tests/test_forms.py
@@ -533,4 +533,4 @@ def test_bug_19349_render_with_none_value(self):
def test_readonly_field_has_changed(self):
field = ReadOnlyPasswordHashField()
- self.assertFalse(field._has_changed('aaa', 'bbb'))
+ self.assertFalse(field.has_changed('aaa', 'bbb'))
View
2  django/contrib/gis/forms/fields.py
@@ -81,7 +81,7 @@ def clean(self, value):
return geom
- def _has_changed(self, initial, data):
+ def has_changed(self, initial, data):
""" Compare geographic value of data with its initial value. """
try:
View
2  django/contrib/gis/tests/geoadmin/tests.py
@@ -44,7 +44,7 @@ def test_olwidget_has_changed(self):
"""
geoadmin = admin.site._registry[City]
form = geoadmin.get_changelist_form(None)()
- has_changed = form.fields['point']._has_changed
+ has_changed = form.fields['point'].has_changed
initial = Point(13.4197458572965953, 52.5194108501149799, srid=4326)
data_same = "SRID=3857;POINT(1493879.2754093995 6894592.019687599)"
View
24 django/forms/fields.py
@@ -25,7 +25,7 @@
from django.utils import formats
from django.utils.encoding import smart_text, force_str, force_text
from django.utils.ipv6 import clean_ipv6_address
-from django.utils.deprecation import RemovedInDjango19Warning, RemovedInDjango20Warning
+from django.utils.deprecation import RemovedInDjango19Warning, RemovedInDjango20Warning, RenameMethodsBase
from django.utils import six
from django.utils.six.moves.urllib.parse import urlsplit, urlunsplit
from django.utils.translation import ugettext_lazy as _, ungettext_lazy
@@ -45,7 +45,13 @@
)
-class Field(object):
+class RenameFieldMethods(RenameMethodsBase):
+ renamed_methods = (
+ ('_has_changed', 'has_changed', RemovedInDjango20Warning),
+ )
+
+
+class Field(six.with_metaclass(RenameFieldMethods, object)):
widget = TextInput # Default widget to use when rendering this type of Field.
hidden_widget = HiddenInput # Default widget to use when rendering this as "hidden".
default_validators = [] # Default set of validators
@@ -185,7 +191,7 @@ def get_limit_choices_to(self):
return self.limit_choices_to()
return self.limit_choices_to
- def _has_changed(self, initial, data):
+ def has_changed(self, initial, data):
"""
Return True if data differs from initial.
"""
@@ -629,7 +635,7 @@ def bound_data(self, data, initial):
return initial
return data
- def _has_changed(self, initial, data):
+ def has_changed(self, initial, data):
if data is None:
return False
return True
@@ -744,7 +750,7 @@ def validate(self, value):
if not value and self.required:
raise ValidationError(self.error_messages['required'], code='required')
- def _has_changed(self, initial, data):
+ def has_changed(self, initial, data):
# Sometimes data or initial could be None or '' which should be the
# same thing as False.
if initial == 'False':
@@ -779,7 +785,7 @@ def to_python(self, value):
def validate(self, value):
pass
- def _has_changed(self, initial, data):
+ def has_changed(self, initial, data):
# None (unknown) and False (No) are not the same
if initial is not None:
initial = bool(initial)
@@ -906,7 +912,7 @@ def validate(self, value):
params={'value': val},
)
- def _has_changed(self, initial, data):
+ def has_changed(self, initial, data):
if initial is None:
initial = []
if data is None:
@@ -1084,14 +1090,14 @@ def compress(self, data_list):
"""
raise NotImplementedError('Subclasses must implement this method.')
- def _has_changed(self, initial, data):
+ def has_changed(self, initial, data):
if initial is None:
initial = ['' for x in range(0, len(data))]
else:
if not isinstance(initial, list):
initial = self.widget.decompress(initial)
for field, initial, data in zip(self.fields, initial, data):
- if field._has_changed(field.to_python(initial), data):
+ if field.has_changed(field.to_python(initial), data):
return True
return False
View
2  django/forms/forms.py
@@ -443,7 +443,7 @@ def changed_data(self):
# Always assume data has changed if validation fails.
self._changed_data.append(name)
continue
- if field._has_changed(initial_value, data_value):
+ if field.has_changed(initial_value, data_value):
self._changed_data.append(name)
return self._changed_data
View
6 django/forms/models.py
@@ -1058,7 +1058,7 @@ def clean(self, value):
raise ValidationError(self.error_messages['invalid_choice'], code='invalid_choice')
return self.parent_instance
- def _has_changed(self, initial, data):
+ def has_changed(self, initial, data):
return False
@@ -1186,7 +1186,7 @@ def to_python(self, value):
def validate(self, value):
return Field.validate(self, value)
- def _has_changed(self, initial, data):
+ def has_changed(self, initial, data):
initial_value = initial if initial is not None else ''
data_value = data if data is not None else ''
return force_text(self.prepare_value(initial_value)) != force_text(data_value)
@@ -1254,7 +1254,7 @@ def prepare_value(self, value):
return [super(ModelMultipleChoiceField, self).prepare_value(v) for v in value]
return super(ModelMultipleChoiceField, self).prepare_value(value)
- def _has_changed(self, initial, data):
+ def has_changed(self, initial, data):
if initial is None:
initial = []
if data is None:
View
3  docs/internals/deprecation.txt
@@ -46,6 +46,9 @@ about each item can often be found in the release notes of two versions prior.
* Support for string ``view`` arguments to ``url()`` will be removed.
+* The backward compatible shim to rename ``django.forms.Form._has_changed()``
+ to ``has_changed()`` will be removed.
+
.. _deprecation-removed-in-1.9:
1.9
View
4 docs/ref/forms/api.txt
@@ -279,7 +279,9 @@ so that the comparison can be done:
>>> f.has_changed()
``has_changed()`` will be ``True`` if the data from ``request.POST`` differs
-from what was provided in :attr:`~Form.initial` or ``False`` otherwise.
+from what was provided in :attr:`~Form.initial` or ``False`` otherwise. The
+result is computed by calling :meth:`Field.has_changed` for each field in the
+form.
Accessing the fields from the form
----------------------------------
View
18 docs/ref/forms/fields.txt
@@ -299,6 +299,24 @@ as the rendered output.
See the :ref:`format localization <format-localization>` documentation for
more information.
+
+Checking if the field data has changed
+--------------------------------------
+
+``has_changed()``
+~~~~~~~~~~~~~~~~~~
+
+.. method:: Field.has_changed()
+
+.. versionchanged:: 1.8
+
+ This method was renamed from ``_has_changed()``.
+
+The ``has_changed()`` method is used to determine if the field value has changed
+from the initial value. Returns ``True`` or ``False``.
+
+See the :class:`Form.has_changed()` documentation for more information.
+
.. _built-in-fields:
Built-in ``Field`` classes
View
6 docs/releases/1.8.txt
@@ -676,3 +676,9 @@ An older (pre-1.0), more restrictive and verbose input format for the
Using the new syntax, this becomes::
``['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]``
+
+``django.forms.Field._has_changed()``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Rename this method to :meth:`~django.forms.Field.has_changed` by removing the
+leading underscore. The old name will still work until Django 2.0.
View
10 tests/forms_tests/tests/test_extra.py
@@ -443,19 +443,19 @@ def compress(self, data_list):
self.assertFormErrors(['This field is required.'], f.clean, ['some text', ['JP']])
# test with no initial data
- self.assertTrue(f._has_changed(None, ['some text', ['J', 'P'], ['2007-04-25', '6:24:00']]))
+ self.assertTrue(f.has_changed(None, ['some text', ['J', 'P'], ['2007-04-25', '6:24:00']]))
# test when the data is the same as initial
- self.assertFalse(f._has_changed('some text,JP,2007-04-25 06:24:00',
+ self.assertFalse(f.has_changed('some text,JP,2007-04-25 06:24:00',
['some text', ['J', 'P'], ['2007-04-25', '6:24:00']]))
# test when the first widget's data has changed
- self.assertTrue(f._has_changed('some text,JP,2007-04-25 06:24:00',
+ self.assertTrue(f.has_changed('some text,JP,2007-04-25 06:24:00',
['other text', ['J', 'P'], ['2007-04-25', '6:24:00']]))
# test when the last widget's data has changed. this ensures that it is not
# short circuiting while testing the widgets.
- self.assertTrue(f._has_changed('some text,JP,2007-04-25 06:24:00',
+ self.assertTrue(f.has_changed('some text,JP,2007-04-25 06:24:00',
['some text', ['J', 'P'], ['2009-04-25', '11:44:00']]))
class ComplexFieldForm(Form):
@@ -803,7 +803,7 @@ def test_l10n(self):
def test_l10n_date_changed(self):
"""
- Ensure that DateField._has_changed() with SelectDateWidget works
+ Ensure that DateField.has_changed() with SelectDateWidget works
correctly with a localized date format.
Refs #17165.
"""
View
92 tests/forms_tests/tests/test_fields.py
@@ -315,12 +315,12 @@ def test_floatfield_localized(self):
def test_floatfield_changed(self):
f = FloatField()
n = 4.35
- self.assertFalse(f._has_changed(n, '4.3500'))
+ self.assertFalse(f.has_changed(n, '4.3500'))
with translation.override('fr'), self.settings(USE_L10N=True):
f = FloatField(localize=True)
localized_n = formats.localize_input(n) # -> '4,35' in French
- self.assertFalse(f._has_changed(n, localized_n))
+ self.assertFalse(f.has_changed(n, localized_n))
# DecimalField ################################################################
@@ -428,13 +428,13 @@ def test_decimalfield_localized(self):
def test_decimalfield_changed(self):
f = DecimalField(max_digits=2, decimal_places=2)
d = Decimal("0.1")
- self.assertFalse(f._has_changed(d, '0.10'))
- self.assertTrue(f._has_changed(d, '0.101'))
+ self.assertFalse(f.has_changed(d, '0.10'))
+ self.assertTrue(f.has_changed(d, '0.101'))
with translation.override('fr'), self.settings(USE_L10N=True):
f = DecimalField(max_digits=2, decimal_places=2, localize=True)
localized_d = formats.localize_input(d) # -> '0,1' in French
- self.assertFalse(f._has_changed(d, localized_d))
+ self.assertFalse(f.has_changed(d, localized_d))
# DateField ###################################################################
@@ -493,7 +493,11 @@ def test_datefield_changed(self):
format = '%d/%m/%Y'
f = DateField(input_formats=[format])
d = datetime.date(2007, 9, 17)
- self.assertFalse(f._has_changed(d, '17/09/2007'))
+ self.assertFalse(f.has_changed(d, '17/09/2007'))
+ # Test for deprecated behavior _has_changed
+ with warnings.catch_warnings(record=True):
+ warnings.simplefilter("always")
+ self.assertFalse(f._has_changed(d, '17/09/2007'))
def test_datefield_strptime(self):
"""Test that field.strptime doesn't raise an UnicodeEncodeError (#16123)"""
@@ -535,9 +539,9 @@ def test_timefield_changed(self):
t1 = datetime.time(12, 51, 34, 482548)
t2 = datetime.time(12, 51)
f = TimeField(input_formats=['%H:%M', '%H:%M %p'])
- self.assertTrue(f._has_changed(t1, '12:51'))
- self.assertFalse(f._has_changed(t2, '12:51'))
- self.assertFalse(f._has_changed(t2, '12:51 PM'))
+ self.assertTrue(f.has_changed(t1, '12:51'))
+ self.assertFalse(f.has_changed(t2, '12:51'))
+ self.assertFalse(f.has_changed(t2, '12:51 PM'))
# DateTimeField ###############################################################
@@ -602,7 +606,7 @@ def test_datetimefield_changed(self):
format = '%Y %m %d %I:%M %p'
f = DateTimeField(input_formats=[format])
d = datetime.datetime(2006, 9, 17, 14, 30, 0)
- self.assertFalse(f._has_changed(d, '2006 09 17 2:30 PM'))
+ self.assertFalse(f.has_changed(d, '2006 09 17 2:30 PM'))
# RegexField ##################################################################
@@ -731,7 +735,7 @@ def test_filefield_3(self):
def test_filefield_changed(self):
'''
- Test for the behavior of _has_changed for FileField. The value of data will
+ Test for the behavior of has_changed for FileField. The value of data will
more than likely come from request.FILES. The value of initial data will
likely be a filename stored in the database. Since its value is of no use to
a FileField it is ignored.
@@ -739,17 +743,17 @@ def test_filefield_changed(self):
f = FileField()
# No file was uploaded and no initial data.
- self.assertFalse(f._has_changed('', None))
+ self.assertFalse(f.has_changed('', None))
# A file was uploaded and no initial data.
- self.assertTrue(f._has_changed('', {'filename': 'resume.txt', 'content': 'My resume'}))
+ self.assertTrue(f.has_changed('', {'filename': 'resume.txt', 'content': 'My resume'}))
# A file was not uploaded, but there is initial data
- self.assertFalse(f._has_changed('resume.txt', None))
+ self.assertFalse(f.has_changed('resume.txt', None))
# A file was uploaded and there is initial data (file identity is not dealt
# 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'}))
# ImageField ##################################################################
@@ -913,15 +917,15 @@ def test_boolean_picklable(self):
def test_booleanfield_changed(self):
f = BooleanField()
- self.assertFalse(f._has_changed(None, None))
- self.assertFalse(f._has_changed(None, ''))
- self.assertFalse(f._has_changed('', None))
- self.assertFalse(f._has_changed('', ''))
- self.assertTrue(f._has_changed(False, 'on'))
- self.assertFalse(f._has_changed(True, 'on'))
- self.assertTrue(f._has_changed(True, ''))
+ self.assertFalse(f.has_changed(None, None))
+ self.assertFalse(f.has_changed(None, ''))
+ self.assertFalse(f.has_changed('', None))
+ self.assertFalse(f.has_changed('', ''))
+ self.assertTrue(f.has_changed(False, 'on'))
+ self.assertFalse(f.has_changed(True, 'on'))
+ self.assertTrue(f.has_changed(True, ''))
# Initial value may have mutated to a string due to show_hidden_initial (#19537)
- self.assertTrue(f._has_changed('False', 'on'))
+ self.assertTrue(f.has_changed('False', 'on'))
# ChoiceField #################################################################
@@ -996,8 +1000,8 @@ def test_typedchoicefield_6(self):
def test_typedchoicefield_has_changed(self):
# has_changed should not trigger required validation
f = TypedChoiceField(choices=[(1, "+1"), (-1, "-1")], coerce=int, required=True)
- self.assertFalse(f._has_changed(None, ''))
- self.assertFalse(f._has_changed(1, '1'))
+ self.assertFalse(f.has_changed(None, ''))
+ self.assertFalse(f.has_changed(1, '1'))
def test_typedchoicefield_special_coerce(self):
"""
@@ -1065,13 +1069,13 @@ class MySQLNullBooleanForm(Form):
def test_nullbooleanfield_changed(self):
f = NullBooleanField()
- self.assertTrue(f._has_changed(False, None))
- self.assertTrue(f._has_changed(None, False))
- self.assertFalse(f._has_changed(None, None))
- self.assertFalse(f._has_changed(False, False))
- self.assertTrue(f._has_changed(True, False))
- self.assertTrue(f._has_changed(True, None))
- self.assertTrue(f._has_changed(True, False))
+ self.assertTrue(f.has_changed(False, None))
+ self.assertTrue(f.has_changed(None, False))
+ self.assertFalse(f.has_changed(None, None))
+ self.assertFalse(f.has_changed(False, False))
+ self.assertTrue(f.has_changed(True, False))
+ self.assertTrue(f.has_changed(True, None))
+ self.assertTrue(f.has_changed(True, False))
# MultipleChoiceField #########################################################
@@ -1116,13 +1120,13 @@ def test_multiplechoicefield_3(self):
def test_multiplechoicefield_changed(self):
f = MultipleChoiceField(choices=[('1', 'One'), ('2', 'Two'), ('3', 'Three')])
- self.assertFalse(f._has_changed(None, None))
- self.assertFalse(f._has_changed([], None))
- self.assertTrue(f._has_changed(None, ['1']))
- self.assertFalse(f._has_changed([1, 2], ['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', '3']))
+ self.assertFalse(f.has_changed(None, None))
+ self.assertFalse(f.has_changed([], None))
+ self.assertTrue(f.has_changed(None, ['1']))
+ self.assertFalse(f.has_changed([1, 2], ['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', '3']))
# TypedMultipleChoiceField ############################################################
# TypedMultipleChoiceField is just like MultipleChoiceField, except that coerced types
@@ -1169,7 +1173,7 @@ def test_typedmultiplechoicefield_7(self):
def test_typedmultiplechoicefield_has_changed(self):
# has_changed should not trigger required validation
f = TypedMultipleChoiceField(choices=[(1, "+1"), (-1, "-1")], coerce=int, required=True)
- self.assertFalse(f._has_changed(None, ''))
+ self.assertFalse(f.has_changed(None, ''))
def test_typedmultiplechoicefield_special_coerce(self):
"""
@@ -1334,7 +1338,7 @@ def test_splitdatetimefield_2(self):
def test_splitdatetimefield_changed(self):
f = SplitDateTimeField(input_date_formats=['%d/%m/%Y'])
- self.assertFalse(f._has_changed(['11/01/2012', '09:18:15'], ['11/01/2012', '09:18:15']))
- self.assertTrue(f._has_changed(datetime.datetime(2008, 5, 6, 12, 40, 00), ['2008-05-06', '12:40:00']))
- self.assertFalse(f._has_changed(datetime.datetime(2008, 5, 6, 12, 40, 00), ['06/05/2008', '12:40']))
- self.assertTrue(f._has_changed(datetime.datetime(2008, 5, 6, 12, 40, 00), ['06/05/2008', '12:41']))
+ self.assertFalse(f.has_changed(['11/01/2012', '09:18:15'], ['11/01/2012', '09:18:15']))
+ self.assertTrue(f.has_changed(datetime.datetime(2008, 5, 6, 12, 40, 00), ['2008-05-06', '12:40:00']))
+ self.assertFalse(f.has_changed(datetime.datetime(2008, 5, 6, 12, 40, 00), ['06/05/2008', '12:40']))
+ self.assertTrue(f.has_changed(datetime.datetime(2008, 5, 6, 12, 40, 00), ['06/05/2008', '12:41']))
Please sign in to comment.
Something went wrong with that request. Please try again.