Skip to content

Commit 0551216

Browse files
authored
Respect allow_null=True on DecimalFields (encode#7718)
* Handle None in to_representation() * Return None as '' in to_representation() when coerce_to_string=True * Handle '' as None in to_internal_value(), for symmetry with to_representation(), and because the empty concept doesn't make sense for Decimal.
1 parent a89a642 commit 0551216

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

rest_framework/fields.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,9 @@ def to_internal_value(self, data):
10631063
try:
10641064
value = decimal.Decimal(data)
10651065
except decimal.DecimalException:
1066+
if data == '' and self.allow_null:
1067+
return None
1068+
10661069
self.fail('invalid')
10671070

10681071
if value.is_nan():
@@ -1112,6 +1115,12 @@ def validate_precision(self, value):
11121115
def to_representation(self, value):
11131116
coerce_to_string = getattr(self, 'coerce_to_string', api_settings.COERCE_DECIMAL_TO_STRING)
11141117

1118+
if value is None:
1119+
if coerce_to_string:
1120+
return ''
1121+
else:
1122+
return None
1123+
11151124
if not isinstance(value, decimal.Decimal):
11161125
value = decimal.Decimal(str(value).strip())
11171126

tests/test_fields.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,9 @@ class TestDecimalField(FieldValues):
10901090
'2E+1': Decimal('20'),
10911091
}
10921092
invalid_inputs = (
1093+
(None, ["This field may not be null."]),
1094+
('', ["A valid number is required."]),
1095+
(' ', ["A valid number is required."]),
10931096
('abc', ["A valid number is required."]),
10941097
(Decimal('Nan'), ["A valid number is required."]),
10951098
(Decimal('Snan'), ["A valid number is required."]),
@@ -1115,6 +1118,32 @@ class TestDecimalField(FieldValues):
11151118
field = serializers.DecimalField(max_digits=3, decimal_places=1)
11161119

11171120

1121+
class TestAllowNullDecimalField(FieldValues):
1122+
valid_inputs = {
1123+
None: None,
1124+
'': None,
1125+
' ': None,
1126+
}
1127+
invalid_inputs = {}
1128+
outputs = {
1129+
None: '',
1130+
}
1131+
field = serializers.DecimalField(max_digits=3, decimal_places=1, allow_null=True)
1132+
1133+
1134+
class TestAllowNullNoStringCoercionDecimalField(FieldValues):
1135+
valid_inputs = {
1136+
None: None,
1137+
'': None,
1138+
' ': None,
1139+
}
1140+
invalid_inputs = {}
1141+
outputs = {
1142+
None: None,
1143+
}
1144+
field = serializers.DecimalField(max_digits=3, decimal_places=1, allow_null=True, coerce_to_string=False)
1145+
1146+
11181147
class TestMinMaxDecimalField(FieldValues):
11191148
"""
11201149
Valid and invalid values for `DecimalField` with min and max limits.

0 commit comments

Comments
 (0)