Fixed #28164 -- Improved float conversions in DecimalField.to_python
Thanks Tim Graham and Adam Johnson for the reviews.
This commit is contained in:
parent
d842ada305
commit
a87189fc5e
|
@ -1508,6 +1508,10 @@ class DecimalField(Field):
|
||||||
validators.DecimalValidator(self.max_digits, self.decimal_places)
|
validators.DecimalValidator(self.max_digits, self.decimal_places)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def context(self):
|
||||||
|
return decimal.Context(prec=self.max_digits)
|
||||||
|
|
||||||
def deconstruct(self):
|
def deconstruct(self):
|
||||||
name, path, args, kwargs = super().deconstruct()
|
name, path, args, kwargs = super().deconstruct()
|
||||||
if self.max_digits is not None:
|
if self.max_digits is not None:
|
||||||
|
@ -1522,6 +1526,8 @@ class DecimalField(Field):
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
return value
|
return value
|
||||||
|
if isinstance(value, float):
|
||||||
|
return self.context.create_decimal_from_float(value)
|
||||||
try:
|
try:
|
||||||
return decimal.Decimal(value)
|
return decimal.Decimal(value)
|
||||||
except decimal.InvalidOperation:
|
except decimal.InvalidOperation:
|
||||||
|
|
|
@ -15,6 +15,12 @@ class DecimalFieldTests(TestCase):
|
||||||
f = models.DecimalField(max_digits=4, decimal_places=2)
|
f = models.DecimalField(max_digits=4, decimal_places=2)
|
||||||
self.assertEqual(f.to_python(3), Decimal('3'))
|
self.assertEqual(f.to_python(3), Decimal('3'))
|
||||||
self.assertEqual(f.to_python('3.14'), Decimal('3.14'))
|
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):
|
with self.assertRaises(ValidationError):
|
||||||
f.to_python('abc')
|
f.to_python('abc')
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue