summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2017-05-03 11:40:09 +0200
committerClaude Paroz <claude@2xlibre.net>2017-05-09 08:40:08 +0200
commita87189fc5e2e874219d20700cf811345138dd365 (patch)
tree7bafa01d0dc87b4d6237854eb6481d2535603566
parentd842ada30524abf410a4de3fc1e539450173800f (diff)
Fixed #28164 -- Improved float conversions in DecimalField.to_python
Thanks Tim Graham and Adam Johnson for the reviews.
-rw-r--r--django/db/models/fields/__init__.py6
-rw-r--r--tests/model_fields/test_decimalfield.py6
2 files changed, 12 insertions, 0 deletions
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index ee48a02d92..2060b0c7b1 100644
--- a/django/db/models/fields/__init__.py
+++ b/django/db/models/fields/__init__.py
@@ -1508,6 +1508,10 @@ class DecimalField(Field):
validators.DecimalValidator(self.max_digits, self.decimal_places)
]
+ @cached_property
+ def context(self):
+ return decimal.Context(prec=self.max_digits)
+
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
if self.max_digits is not None:
@@ -1522,6 +1526,8 @@ class DecimalField(Field):
def to_python(self, value):
if value is None:
return value
+ if isinstance(value, float):
+ return self.context.create_decimal_from_float(value)
try:
return decimal.Decimal(value)
except decimal.InvalidOperation:
diff --git a/tests/model_fields/test_decimalfield.py b/tests/model_fields/test_decimalfield.py
index 2f4540c81d..5163d8188b 100644
--- a/tests/model_fields/test_decimalfield.py
+++ b/tests/model_fields/test_decimalfield.py
@@ -15,6 +15,12 @@ class DecimalFieldTests(TestCase):
f = models.DecimalField(max_digits=4, decimal_places=2)
self.assertEqual(f.to_python(3), Decimal('3'))
self.assertEqual(f.to_python('3.14'), Decimal('3.14'))
+ # to_python() converts floats and honors max_digits.
+ self.assertEqual(f.to_python(3.1415926535897), Decimal('3.142'))
+ self.assertEqual(f.to_python(2.4), Decimal('2.400'))
+ # Uses default rounding of ROUND_HALF_EVEN.
+ self.assertEqual(f.to_python(2.0625), Decimal('2.062'))
+ self.assertEqual(f.to_python(2.1875), Decimal('2.188'))
with self.assertRaises(ValidationError):
f.to_python('abc')