Skip to content

Commit

Permalink
Merge pull request #2695 from delinhabit/refactor-decimalfield
Browse files Browse the repository at this point in the history
[enhancement] Refactored DecimalField to allow easier subclassing
  • Loading branch information
tomchristie committed Jun 4, 2015
2 parents 0c66c7c + 022c4d5 commit e8cc948
Showing 1 changed file with 24 additions and 10 deletions.
34 changes: 24 additions & 10 deletions rest_framework/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -775,10 +775,8 @@ def __init__(self, max_digits, decimal_places, coerce_to_string=None, max_value=

def to_internal_value(self, data):
"""
Validates that the input is a decimal number. Returns a Decimal
instance. Returns None for empty values. Ensures that there are no more
than max_digits in the number, and no more than decimal_places digits
after the decimal point.
Validate that the input is a decimal number and return a Decimal
instance.
"""
data = smart_text(data).strip()
if len(data) > self.MAX_STRING_LENGTH:
Expand All @@ -798,6 +796,16 @@ def to_internal_value(self, data):
if value in (decimal.Decimal('Inf'), decimal.Decimal('-Inf')):
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()
decimals = exponent * decimal.Decimal(-1) if exponent < 0 else 0

Expand All @@ -824,16 +832,22 @@ def to_representation(self, value):
if not isinstance(value, decimal.Decimal):
value = decimal.Decimal(six.text_type(value).strip())

context = decimal.getcontext().copy()
context.prec = self.max_digits
quantized = value.quantize(
decimal.Decimal('.1') ** self.decimal_places,
context=context
)
quantized = self.quantize(value)

if not self.coerce_to_string:
return 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...

Expand Down

0 comments on commit e8cc948

Please sign in to comment.