diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 0a96d0e0c7..4b4ea83cc1 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -295,6 +295,7 @@ Corresponds to `django.db.models.fields.DecimalField`. * `min_value` Validate that the number provided is no less than this value. * `localize` Set to `True` to enable localization of input and output based on the current locale. This will also force `coerce_to_string` to `True`. Defaults to `False`. Note that data formatting is enabled if you have set `USE_L10N=True` in your settings file. * `rounding` Sets the rounding mode used when quantising to the configured precision. Valid values are [`decimal` module rounding modes][python-decimal-rounding-modes]. Defaults to `None`. +* `normalize_output` Will normalize the decimal value when serialized. This will strip all trailing zeroes and change the value's precision to the minimum required precision to be able to represent the value without loosing data. Defaults to `False`. #### Example usage diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 7f4c83b5df..88d606b282 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -963,10 +963,11 @@ class DecimalField(Field): MAX_STRING_LENGTH = 1000 # Guard against malicious string inputs. def __init__(self, max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None, - localize=False, rounding=None, **kwargs): + localize=False, rounding=None, normalize_output=False, **kwargs): self.max_digits = max_digits self.decimal_places = decimal_places self.localize = localize + self.normalize_output = normalize_output if coerce_to_string is not None: self.coerce_to_string = coerce_to_string if self.localize: @@ -1079,6 +1080,9 @@ def to_representation(self, value): quantized = self.quantize(value) + if self.normalize_output: + quantized = quantized.normalize() + if not coerce_to_string: return quantized if self.localize: diff --git a/tests/test_fields.py b/tests/test_fields.py index 72ef23dca5..3112fc2cce 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1251,6 +1251,27 @@ def test_part_precision_string_quantized_value_for_decimal(self): assert value == expected_digit_tuple +class TestNormalizedOutputValueDecimalField(TestCase): + """ + Test that we get the expected behavior of on DecimalField when normalize=True + """ + + def test_normalize_output(self): + field = serializers.DecimalField(max_digits=4, decimal_places=3, normalize_output=True) + output = field.to_representation(Decimal('1.000')) + assert output == '1' + + def test_non_normalize_output(self): + field = serializers.DecimalField(max_digits=4, decimal_places=3, normalize_output=False) + output = field.to_representation(Decimal('1.000')) + assert output == '1.000' + + def test_normalize_coeherce_to_string(self): + field = serializers.DecimalField(max_digits=4, decimal_places=3, normalize_output=True, coerce_to_string=False) + output = field.to_representation(Decimal('1.000')) + assert output == Decimal('1') + + class TestNoDecimalPlaces(FieldValues): valid_inputs = { '0.12345': Decimal('0.12345'),