diff --git a/django/forms/fields.py b/django/forms/fields.py index c4bc3fa88cb..7711cd65ad7 100644 --- a/django/forms/fields.py +++ b/django/forms/fields.py @@ -370,8 +370,14 @@ class DecimalField(IntegerField): def widget_attrs(self, widget): attrs = super(DecimalField, self).widget_attrs(widget) - if isinstance(widget, NumberInput) and self.decimal_places: - attrs['step'] = '0.%s1' % ('0' * (self.decimal_places - 1)) + if isinstance(widget, NumberInput): + if self.decimal_places is not None: + # Use exponential notation for small values since they might + # be parsed as 0 otherwise. ref #20765 + step = str(Decimal('1') / 10 ** self.decimal_places).lower() + else: + step = 'any' + attrs.setdefault('step', step) return attrs diff --git a/tests/forms_tests/tests/test_fields.py b/tests/forms_tests/tests/test_fields.py index f7d83503f49..dab67b4366a 100644 --- a/tests/forms_tests/tests/test_fields.py +++ b/tests/forms_tests/tests/test_fields.py @@ -374,6 +374,17 @@ class FieldsTests(SimpleTestCase): self.assertEqual(f.clean('.01'), Decimal(".01")) self.assertRaisesMessage(ValidationError, "'Ensure that there are no more than 0 digits before the decimal point.'", f.clean, '1.1') + def test_decimalfield_widget_attrs(self): + f = DecimalField(max_digits=6, decimal_places=2) + self.assertEqual(f.widget_attrs(Widget()), {}) + self.assertEqual(f.widget_attrs(NumberInput()), {'step': '0.01'}) + f = DecimalField(max_digits=10, decimal_places=0) + self.assertEqual(f.widget_attrs(NumberInput()), {'step': '1'}) + f = DecimalField(max_digits=19, decimal_places=19) + self.assertEqual(f.widget_attrs(NumberInput()), {'step': '1e-19'}) + f = DecimalField(max_digits=20) + self.assertEqual(f.widget_attrs(NumberInput()), {'step': 'any'}) + def test_decimalfield_localized(self): """ Make sure localized DecimalField's widget renders to a text input with diff --git a/tests/model_formsets/tests.py b/tests/model_formsets/tests.py index 09a3ba17788..4411bbf59aa 100644 --- a/tests/model_formsets/tests.py +++ b/tests/model_formsets/tests.py @@ -576,7 +576,7 @@ class ModelFormsetTest(TestCase): formset = AuthorBooksFormSet2(instance=author) self.assertEqual(len(formset.forms), 1) self.assertHTMLEqual(formset.forms[0].as_p(), - '

\n' + '

\n' '

') data = {