Skip to content

Commit 022c4d5

Browse files
committed
Refactored DecimalField to allow easier subclassing
1 parent b41808b commit 022c4d5

File tree

1 file changed

+24
-10
lines changed

1 file changed

+24
-10
lines changed

rest_framework/fields.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -757,10 +757,8 @@ def __init__(self, max_digits, decimal_places, coerce_to_string=None, max_value=
757757

758758
def to_internal_value(self, data):
759759
"""
760-
Validates that the input is a decimal number. Returns a Decimal
761-
instance. Returns None for empty values. Ensures that there are no more
762-
than max_digits in the number, and no more than decimal_places digits
763-
after the decimal point.
760+
Validate that the input is a decimal number and return a Decimal
761+
instance.
764762
"""
765763
data = smart_text(data).strip()
766764
if len(data) > self.MAX_STRING_LENGTH:
@@ -780,6 +778,16 @@ def to_internal_value(self, data):
780778
if value in (decimal.Decimal('Inf'), decimal.Decimal('-Inf')):
781779
self.fail('invalid')
782780

781+
return self.validate_precision(value)
782+
783+
def validate_precision(self, value):
784+
"""
785+
Ensure that there are no more than max_digits in the number, and no
786+
more than decimal_places digits after the decimal point.
787+
788+
Override this method to disable the precision validation for input
789+
values or to enhance it in any way you need to.
790+
"""
783791
sign, digittuple, exponent = value.as_tuple()
784792
decimals = abs(exponent)
785793
# digittuple doesn't include any leading zeros.
@@ -805,16 +813,22 @@ def to_representation(self, value):
805813
if not isinstance(value, decimal.Decimal):
806814
value = decimal.Decimal(six.text_type(value).strip())
807815

808-
context = decimal.getcontext().copy()
809-
context.prec = self.max_digits
810-
quantized = value.quantize(
811-
decimal.Decimal('.1') ** self.decimal_places,
812-
context=context
813-
)
816+
quantized = self.quantize(value)
817+
814818
if not self.coerce_to_string:
815819
return quantized
816820
return '{0:f}'.format(quantized)
817821

822+
def quantize(self, value):
823+
"""
824+
Quantize the decimal value to the configured precision.
825+
"""
826+
context = decimal.getcontext().copy()
827+
context.prec = self.max_digits
828+
return value.quantize(
829+
decimal.Decimal('.1') ** self.decimal_places,
830+
context=context)
831+
818832

819833
# Date & time fields...
820834

0 commit comments

Comments
 (0)