From 7aec160e44a0a32bcec661b838dff625bd045531 Mon Sep 17 00:00:00 2001
From: Simon Charette <charette.s@gmail.com>
Date: Thu, 18 Jul 2013 22:01:51 -0400
Subject: [PATCH] Fixed #20765 -- Avoid setting `step` on `NumberInput` when
`max_digits` > 18.
Browser parse 10^-18 as 0 which is an invalid value for this attribute.
Thanks to Trac alias matklad for the report.
---
django/forms/fields.py | 9 +++++++--
tests/forms_tests/tests/test_fields.py | 9 +++++++++
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/django/forms/fields.py b/django/forms/fields.py
index c4bc3fa8..1f7a5f2 100644
a
|
b
|
class DecimalField(IntegerField):
|
370 | 370 | |
371 | 371 | def widget_attrs(self, widget): |
372 | 372 | attrs = super(DecimalField, self).widget_attrs(widget) |
373 | | if isinstance(widget, NumberInput) and self.decimal_places: |
374 | | attrs['step'] = '0.%s1' % ('0' * (self.decimal_places - 1)) |
| 373 | if isinstance(widget, NumberInput): |
| 374 | # `step` < 10^-18 is parsed as 0. ref #20765 |
| 375 | if self.decimal_places and self.decimal_places <= 18: |
| 376 | step = "0.%s1" % ('0' * (self.decimal_places - 1)) |
| 377 | else: |
| 378 | step = 'any' |
| 379 | attrs.setdefault('step', step) |
375 | 380 | return attrs |
376 | 381 | |
377 | 382 | |
diff --git a/tests/forms_tests/tests/test_fields.py b/tests/forms_tests/tests/test_fields.py
index f7d8350..eb28462 100644
a
|
b
|
class FieldsTests(SimpleTestCase):
|
374 | 374 | self.assertEqual(f.clean('.01'), Decimal(".01")) |
375 | 375 | self.assertRaisesMessage(ValidationError, "'Ensure that there are no more than 0 digits before the decimal point.'", f.clean, '1.1') |
376 | 376 | |
| 377 | def test_decimal_field_widget_attrs(self): |
| 378 | f = DecimalField(max_digits=6, decimal_places=2) |
| 379 | self.assertEqual(f.widget_attrs(Widget()), {}) |
| 380 | self.assertEqual(f.widget_attrs(NumberInput()), {'step': '0.01'}) |
| 381 | f = DecimalField(max_digits=19, decimal_places=19) |
| 382 | self.assertEqual(f.widget_attrs(NumberInput()), {'step': 'any'}) |
| 383 | f = DecimalField(max_digits=20) |
| 384 | self.assertEqual(f.widget_attrs(NumberInput()), {'step': 'any'}) |
| 385 | |
377 | 386 | def test_decimalfield_localized(self): |
378 | 387 | """ |
379 | 388 | Make sure localized DecimalField's widget renders to a text input with |