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.
This commit is contained in:
parent
6d52844b9b
commit
415a36947c
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
Loading…
Reference in New Issue