From dcb42cd13752fe2d583652e48ac97ea6e48d8d56 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 -- Use exponential form to set `step` attribute
on `NumberInput`.
Browsers 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 | 8 ++++++--
tests/forms_tests/tests/test_fields.py | 11 +++++++++++
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/django/forms/fields.py b/django/forms/fields.py
index c4bc3fa8..1edf10a 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 | if self.decimal_places is not None: |
| 375 | step = str(Decimal('1') / 10 ** self.decimal_places).lower() |
| 376 | else: |
| 377 | step = 'any' |
| 378 | attrs.setdefault('step', step) |
375 | 379 | return attrs |
376 | 380 | |
377 | 381 | |
diff --git a/tests/forms_tests/tests/test_fields.py b/tests/forms_tests/tests/test_fields.py
index f7d8350..dab67b4 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_decimalfield_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=10, decimal_places=0) |
| 382 | self.assertEqual(f.widget_attrs(NumberInput()), {'step': '1'}) |
| 383 | f = DecimalField(max_digits=19, decimal_places=19) |
| 384 | self.assertEqual(f.widget_attrs(NumberInput()), {'step': '1e-19'}) |
| 385 | f = DecimalField(max_digits=20) |
| 386 | self.assertEqual(f.widget_attrs(NumberInput()), {'step': 'any'}) |
| 387 | |
377 | 388 | def test_decimalfield_localized(self): |
378 | 389 | """ |
379 | 390 | Make sure localized DecimalField's widget renders to a text input with |