Skip to content

Commit d5f228d

Browse files
Krolkentomchristie
andauthored
Possibility to remove trailing zeros on DecimalFields representation (#6514)
* Added normalize parameter to DecimalField to be able to strip trailing zeros. Fixes #6151. * Updated docs to include normalize option on DecimalField * Fixed linting error in test_fields * Removed comment and renamed normalize to normalize_output as suggested in code review Co-authored-by: Tom Christie <[email protected]>
1 parent 78cdae6 commit d5f228d

File tree

3 files changed

+27
-1
lines changed

3 files changed

+27
-1
lines changed

docs/api-guide/fields.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ Corresponds to `django.db.models.fields.DecimalField`.
295295
* `min_value` Validate that the number provided is no less than this value.
296296
* `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.
297297
* `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`.
298+
* `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`.
298299

299300
#### Example usage
300301

rest_framework/fields.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -963,10 +963,11 @@ class DecimalField(Field):
963963
MAX_STRING_LENGTH = 1000 # Guard against malicious string inputs.
964964

965965
def __init__(self, max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None,
966-
localize=False, rounding=None, **kwargs):
966+
localize=False, rounding=None, normalize_output=False, **kwargs):
967967
self.max_digits = max_digits
968968
self.decimal_places = decimal_places
969969
self.localize = localize
970+
self.normalize_output = normalize_output
970971
if coerce_to_string is not None:
971972
self.coerce_to_string = coerce_to_string
972973
if self.localize:
@@ -1079,6 +1080,9 @@ def to_representation(self, value):
10791080

10801081
quantized = self.quantize(value)
10811082

1083+
if self.normalize_output:
1084+
quantized = quantized.normalize()
1085+
10821086
if not coerce_to_string:
10831087
return quantized
10841088
if self.localize:

tests/test_fields.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,27 @@ def test_part_precision_string_quantized_value_for_decimal(self):
12511251
assert value == expected_digit_tuple
12521252

12531253

1254+
class TestNormalizedOutputValueDecimalField(TestCase):
1255+
"""
1256+
Test that we get the expected behavior of on DecimalField when normalize=True
1257+
"""
1258+
1259+
def test_normalize_output(self):
1260+
field = serializers.DecimalField(max_digits=4, decimal_places=3, normalize_output=True)
1261+
output = field.to_representation(Decimal('1.000'))
1262+
assert output == '1'
1263+
1264+
def test_non_normalize_output(self):
1265+
field = serializers.DecimalField(max_digits=4, decimal_places=3, normalize_output=False)
1266+
output = field.to_representation(Decimal('1.000'))
1267+
assert output == '1.000'
1268+
1269+
def test_normalize_coeherce_to_string(self):
1270+
field = serializers.DecimalField(max_digits=4, decimal_places=3, normalize_output=True, coerce_to_string=False)
1271+
output = field.to_representation(Decimal('1.000'))
1272+
assert output == Decimal('1')
1273+
1274+
12541275
class TestNoDecimalPlaces(FieldValues):
12551276
valid_inputs = {
12561277
'0.12345': Decimal('0.12345'),

0 commit comments

Comments
 (0)