Opened 10 years ago

Closed 10 years ago

#24229 closed New feature (fixed)

forms.IntegerField.clean() fails to clean float objects that are integers

Reported by: Jon Dufresne Owned by: nobody
Component: Forms Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Django forms are useful for validating user input beyond just HTML forms. They can be used to validate and clean user input from multiple sources.

One source could potentially be an spreadsheets. Imagine a spreadsheet where each row is data keyed by its header. Each row is validated by a Django Form object, if the form is valid, some action occurs.

One issue, MS Excel represents all numbers in cells as floats, even integers. So for this to work, a float with value 1.0 should be cleaned by forms.IntegerField as 1. Currently this fails as forms.IntegerField.to_python() is implemeted as:

try:
    value = int(str(value))
except (ValueError, TypeError):
    raise ValidationError(self.error_messages['invalid'], code='invalid')

But this fails for floats:

$ python -c 'int(str(1.0))'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '1.0'

The following test demonstrates that this does not work in Django:

$ git diff
diff --git a/tests/forms_tests/tests/test_fields.py b/tests/forms_tests/tests/test_fields.py
index fda4512..3069520 100644
--- a/tests/forms_tests/tests/test_fields.py
+++ b/tests/forms_tests/tests/test_fields.py
@@ -184,6 +184,7 @@ class FieldsTests(SimpleTestCase):
         self.assertRaisesMessage(ValidationError, "'Enter a whole number.'", f.clean, '1a')
         self.assertEqual(f.max_value, None)
         self.assertEqual(f.min_value, None)
+        self.assertEqual(1, f.clean(1.0))
 
     def test_integerfield_2(self):
         f = IntegerField(required=False)

I propose that the fields.IntegerField be able to clean float objects that represent an integer. This will help make Django forms useful for user input beyond simple HTML forms.

Change History (3)

comment:2 by Wim Feijen, 10 years ago

Triage Stage: UnreviewedAccepted

comment:3 by Claude Paroz <claude@…>, 10 years ago

Resolution: fixed
Status: newclosed

In 3b966c2b73c420222d1524cda03c1a5626c90fe6:

Fixed #24229 -- Changed IntegerField to clean floats representing integers

Note: See TracTickets for help on using tickets.
Back to Top