diff options
| author | Claude Paroz <claude@2xlibre.net> | 2017-05-03 11:40:09 +0200 |
|---|---|---|
| committer | Claude Paroz <claude@2xlibre.net> | 2017-05-09 08:40:08 +0200 |
| commit | a87189fc5e2e874219d20700cf811345138dd365 (patch) | |
| tree | 7bafa01d0dc87b4d6237854eb6481d2535603566 | |
| parent | d842ada30524abf410a4de3fc1e539450173800f (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__.py | 6 | ||||
| -rw-r--r-- | tests/model_fields/test_decimalfield.py | 6 |
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') |
