diff --git a/django/forms/fields.py b/django/forms/fields.py index 6d1c14586e..44bbfd8e6f 100644 --- a/django/forms/fields.py +++ b/django/forms/fields.py @@ -236,6 +236,7 @@ class IntegerField(Field): default_error_messages = { 'invalid': _('Enter a whole number.'), } + re_decimal = re.compile(r'\.0*\s*$') def __init__(self, max_value=None, min_value=None, *args, **kwargs): self.max_value, self.min_value = max_value, min_value @@ -259,8 +260,9 @@ class IntegerField(Field): return None if self.localize: value = formats.sanitize_separators(value) + # Strip trailing decimal and zeros. try: - value = int(str(value)) + value = int(self.re_decimal.sub('', str(value))) except (ValueError, TypeError): raise ValidationError(self.error_messages['invalid'], code='invalid') return value diff --git a/tests/forms_tests/tests/test_fields.py b/tests/forms_tests/tests/test_fields.py index 477beee210..e70dc3c267 100644 --- a/tests/forms_tests/tests/test_fields.py +++ b/tests/forms_tests/tests/test_fields.py @@ -247,6 +247,23 @@ class FieldsTests(SimpleTestCase): f1 = IntegerField(localize=True) self.assertWidgetRendersTo(f1, '') + def test_integerfield_float(self): + f = IntegerField() + self.assertEqual(1, f.clean(1.0)) + self.assertEqual(1, f.clean('1.0')) + self.assertEqual(1, f.clean(b'1.0')) + self.assertEqual(1, f.clean(' 1.0 ')) + self.assertEqual(1, f.clean('1.')) + self.assertEqual(1, f.clean(' 1. ')) + self.assertRaisesMessage(ValidationError, "'Enter a whole number.'", f.clean, '1.5') + self.assertRaisesMessage(ValidationError, "'Enter a whole number.'", f.clean, '…') + + def test_integerfield_big_num(self): + f = IntegerField() + self.assertEqual(9223372036854775808, f.clean(9223372036854775808)) + self.assertEqual(9223372036854775808, f.clean('9223372036854775808')) + self.assertEqual(9223372036854775808, f.clean('9223372036854775808.0')) + def test_integerfield_subclass(self): """ Test that class-defined widget is not overwritten by __init__ (#22245).