Commit 022c4d54 by Ion Scerbatiuc

Refactored DecimalField to allow easier subclassing

parent b41808b7
...@@ -757,10 +757,8 @@ class DecimalField(Field): ...@@ -757,10 +757,8 @@ class DecimalField(Field):
def to_internal_value(self, data): def to_internal_value(self, data):
""" """
Validates that the input is a decimal number. Returns a Decimal Validate that the input is a decimal number and return a Decimal
instance. Returns None for empty values. Ensures that there are no more instance.
than max_digits in the number, and no more than decimal_places digits
after the decimal point.
""" """
data = smart_text(data).strip() data = smart_text(data).strip()
if len(data) > self.MAX_STRING_LENGTH: if len(data) > self.MAX_STRING_LENGTH:
...@@ -780,6 +778,16 @@ class DecimalField(Field): ...@@ -780,6 +778,16 @@ class DecimalField(Field):
if value in (decimal.Decimal('Inf'), decimal.Decimal('-Inf')): if value in (decimal.Decimal('Inf'), decimal.Decimal('-Inf')):
self.fail('invalid') self.fail('invalid')
return self.validate_precision(value)
def validate_precision(self, value):
"""
Ensure that there are no more than max_digits in the number, and no
more than decimal_places digits after the decimal point.
Override this method to disable the precision validation for input
values or to enhance it in any way you need to.
"""
sign, digittuple, exponent = value.as_tuple() sign, digittuple, exponent = value.as_tuple()
decimals = abs(exponent) decimals = abs(exponent)
# digittuple doesn't include any leading zeros. # digittuple doesn't include any leading zeros.
...@@ -805,16 +813,22 @@ class DecimalField(Field): ...@@ -805,16 +813,22 @@ class DecimalField(Field):
if not isinstance(value, decimal.Decimal): if not isinstance(value, decimal.Decimal):
value = decimal.Decimal(six.text_type(value).strip()) value = decimal.Decimal(six.text_type(value).strip())
context = decimal.getcontext().copy() quantized = self.quantize(value)
context.prec = self.max_digits
quantized = value.quantize(
decimal.Decimal('.1') ** self.decimal_places,
context=context
)
if not self.coerce_to_string: if not self.coerce_to_string:
return quantized return quantized
return '{0:f}'.format(quantized) return '{0:f}'.format(quantized)
def quantize(self, value):
"""
Quantize the decimal value to the configured precision.
"""
context = decimal.getcontext().copy()
context.prec = self.max_digits
return value.quantize(
decimal.Decimal('.1') ** self.decimal_places,
context=context)
# Date & time fields... # Date & time fields...
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment