summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2013-07-18 22:01:51 -0400
committerSimon Charette <charette.s@gmail.com>2013-07-19 23:31:15 -0400
commit415a36947cb4b8b61230698e13cca2df9400e245 (patch)
tree9591e0724eb62931c8cb3990cb44616e1a3b3289
parent6d52844b9b3c0bd18eea03ac9dc499782b84c36b (diff)
Fixed #20765 -- Set small values of `step` using exponential notation.
Browsers parse small factors of 10 as 0 under decimal notation. Thanks to Trac alias matklad for the report and Claude Paroz for the review.
-rw-r--r--django/forms/fields.py10
-rw-r--r--tests/forms_tests/tests/test_fields.py11
-rw-r--r--tests/model_formsets/tests.py2
3 files changed, 20 insertions, 3 deletions
diff --git a/django/forms/fields.py b/django/forms/fields.py
index c4bc3fa88c..7711cd65ad 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 f7d83503f4..dab67b4366 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 09a3ba1778..4411bbf59a 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(),
- '<p><label for="id_bookwithcustompk_set-0-my_pk">My pk:</label> <input id="id_bookwithcustompk_set-0-my_pk" type="number" name="bookwithcustompk_set-0-my_pk" /></p>\n'
+ '<p><label for="id_bookwithcustompk_set-0-my_pk">My pk:</label> <input id="id_bookwithcustompk_set-0-my_pk" type="number" name="bookwithcustompk_set-0-my_pk" step="1" /></p>\n'
'<p><label for="id_bookwithcustompk_set-0-title">Title:</label> <input id="id_bookwithcustompk_set-0-title" type="text" name="bookwithcustompk_set-0-title" maxlength="100" /><input type="hidden" name="bookwithcustompk_set-0-author" value="1" id="id_bookwithcustompk_set-0-author" /></p>')
data = {