Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #8290 -- Fixed DecimalField's cleaning of values with a large n…

…umber of decimal places, based on patch from dgouldin.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@8391 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 727133109cfb37d73da38d760198eb300125ddb0 1 parent 9d1ec0b
@gdub gdub authored
Showing with 42 additions and 5 deletions.
  1. +15 −5 django/forms/fields.py
  2. +27 −0 tests/regressiontests/forms/fields.py
View
20 django/forms/fields.py
@@ -244,18 +244,28 @@ def clean(self, value):
value = Decimal(value)
except DecimalException:
raise ValidationError(self.error_messages['invalid'])
- pieces = str(value).lstrip("-").split('.')
- decimals = (len(pieces) == 2) and len(pieces[1]) or 0
- digits = len(pieces[0])
+
+ sign, digittuple, exponent = value.as_tuple()
+ decimals = abs(exponent)
+ # digittuple doesn't include any leading zeros.
+ digits = len(digittuple)
+ if decimals >= digits:
+ # We have leading zeros up to or past the decimal point. Count
+ # everything past the decimal point as a digit. We also add one
+ # for leading zeros before the decimal point (any number of leading
+ # whole zeros collapse to one digit).
+ digits = decimals + 1
+ whole_digits = digits - decimals
+
if self.max_value is not None and value > self.max_value:
raise ValidationError(self.error_messages['max_value'] % self.max_value)
if self.min_value is not None and value < self.min_value:
raise ValidationError(self.error_messages['min_value'] % self.min_value)
- if self.max_digits is not None and (digits + decimals) > self.max_digits:
+ if self.max_digits is not None and digits > self.max_digits:
raise ValidationError(self.error_messages['max_digits'] % self.max_digits)
if self.decimal_places is not None and decimals > self.decimal_places:
raise ValidationError(self.error_messages['max_decimal_places'] % self.decimal_places)
- if self.max_digits is not None and self.decimal_places is not None and digits > (self.max_digits - self.decimal_places):
+ if self.max_digits is not None and self.decimal_places is not None and whole_digits > (self.max_digits - self.decimal_places):
raise ValidationError(self.error_messages['max_whole_digits'] % (self.max_digits - self.decimal_places))
return value
View
27 tests/regressiontests/forms/fields.py
@@ -403,6 +403,33 @@
>>> f.clean('00.50') == Decimal("0.50")
True
+
+>>> f = DecimalField(decimal_places=2)
+>>> f.clean('0.00000001')
+Traceback (most recent call last):
+...
+ValidationError: [u'Ensure that there are no more than 2 decimal places.']
+
+
+>>> f = DecimalField(max_digits=3)
+
+# Leading whole zeros "collapse" to one digit.
+>>> f.clean('0000000.10') == Decimal("0.1")
+True
+>>> f.clean('0000000.100')
+Traceback (most recent call last):
+...
+ValidationError: [u'Ensure that there are no more than 3 digits in total.']
+
+# Only leading whole zeros "collapse" to one digit.
+>>> f.clean('000000.02') == Decimal('0.02')
+True
+>>> f.clean('000000.002')
+Traceback (most recent call last):
+...
+ValidationError: [u'Ensure that there are no more than 3 digits in total.']
+
+
# DateField ###################################################################
>>> import datetime
Please sign in to comment.
Something went wrong with that request. Please try again.