Code

Ticket #15775: ticket_15775.2.diff

File ticket_15775.2.diff, 4.7 KB (added by samufuentes, 3 years ago)
Line 
1diff --git a/django/forms/fields.py b/django/forms/fields.py
2index a5ea81d..02fc7ef 100644
3--- a/django/forms/fields.py
4+++ b/django/forms/fields.py
5@@ -301,23 +301,30 @@ class DecimalField(Field):
6         if value != value or value == Decimal("Inf") or value == Decimal("-Inf"):
7             raise ValidationError(self.error_messages['invalid'])
8         sign, digittuple, exponent = value.as_tuple()
9-        decimals = abs(exponent)
10-        # digittuple doesn't include any leading zeros.
11-        digits = len(digittuple)
12-        if decimals > digits:
13-            # We have leading zeros up to or past the decimal point.  Count
14-            # everything past the decimal point as a digit.  We do not count
15-            # 0 before the decimal point as a digit since that would mean
16-            # we would not allow max_digits = decimal_places.
17-            digits = decimals
18-        whole_digits = digits - decimals
19-
20-        if self.max_digits is not None and digits > self.max_digits:
21-            raise ValidationError(self.error_messages['max_digits'] % self.max_digits)
22-        if self.decimal_places is not None and decimals > self.decimal_places:
23-            raise ValidationError(self.error_messages['max_decimal_places'] % self.decimal_places)
24-        if self.max_digits is not None and self.decimal_places is not None and whole_digits > (self.max_digits - self.decimal_places):
25-            raise ValidationError(self.error_messages['max_whole_digits'] % (self.max_digits - self.decimal_places))
26+        if exponent < 0:
27+            decimals = abs(exponent)
28+            # digittuple doesn't include any leading zeros.
29+            digits = len(digittuple)
30+            if decimals > digits:
31+                # We have leading zeros up to or past the decimal point.  Count
32+                # everything past the decimal point as a digit.  We do not count
33+                # 0 before the decimal point as a digit since that would mean
34+                # we would not allow max_digits = decimal_places.
35+                digits = decimals
36+            whole_digits = digits - decimals
37+
38+            if self.max_digits is not None and digits > self.max_digits:
39+                raise ValidationError(self.error_messages['max_digits'] % self.max_digits)
40+            if self.decimal_places is not None and decimals > self.decimal_places:
41+                raise ValidationError(self.error_messages['max_decimal_places'] % self.decimal_places)
42+            if self.max_digits is not None and self.decimal_places is not None and whole_digits > (self.max_digits - self.decimal_places):
43+                raise ValidationError(self.error_messages['max_whole_digits'] % (self.max_digits - self.decimal_places))
44+        else:
45+            digits = len(digittuple) + exponent
46+            if self.max_digits is not None and digits > self.max_digits:
47+                raise ValidationError(self.error_messages['max_digits'] % self.max_digits)
48+
49+
50         return value
51 
52 class BaseTemporalField(Field):
53diff --git a/tests/regressiontests/forms/tests/__init__.py b/tests/regressiontests/forms/tests/__init__.py
54index 39db39f..5543fac 100644
55--- a/tests/regressiontests/forms/tests/__init__.py
56+++ b/tests/regressiontests/forms/tests/__init__.py
57@@ -8,7 +8,7 @@ from media import *
58 from models import *
59 from regressions import *
60 from util import *
61-from validators import TestFieldWithValidators
62+from validators import *
63 from widgets import *
64 
65 from regressiontests.forms.localflavortests import (
66diff --git a/tests/regressiontests/forms/tests/validators.py b/tests/regressiontests/forms/tests/validators.py
67index cadf660..eb04b7e 100644
68--- a/tests/regressiontests/forms/tests/validators.py
69+++ b/tests/regressiontests/forms/tests/validators.py
70@@ -1,7 +1,10 @@
71+from decimal import Decimal
72+
73 from django import forms
74 from django.core import validators
75 from django.core.exceptions import ValidationError
76 from django.utils.unittest import TestCase
77+from django import test
78 
79 
80 class TestFieldWithValidators(TestCase):
81@@ -14,3 +17,14 @@ class TestFieldWithValidators(TestCase):
82             field.clean('not int nor mail')
83         except ValidationError, e:
84             self.assertEqual(2, len(e.messages))
85+
86+class DecimalFieldTests(test.TestCase):
87+    def test_validate(self):
88+        f = forms.DecimalField(max_digits=10, decimal_places=1)
89+        try:
90+            f.validate(Decimal('1E+2'))  # Ensure that scientific notation with positive exponent is accepted (#15775)
91+            f.validate(Decimal('1E-1'))
92+            f.validate(Decimal('100'))
93+        except ValidationError:
94+            self.fail("Validation is not working properly")
95+        self.assertRaises(ValidationError, f.validate, Decimal('1E-2'))
96\ No newline at end of file