Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Edge case DecimalField serialization #9135

Unanswered
szymonhab asked this question in Potential Issue
Discussion options

Hey, i've noticed a strange behavior in Decimal serialization

In theory i shouldn't expect any error here. Especially that this code fired after running for few months on production - only when serialized value is greater or equal to 1.0

Same bug occurs for serializers.DecimalField(decimal_places=3, max_digits=4) configuration - when value is greater or equal to 10

In theory this isn't a problem when someone serializes verified data from psql, this time I serialize raw python objects to json payload and decimals should be rounded up somehow?

Possible solution could be to just cut decimal part that can't fit into the configured places

In [51]: class TestDecimal(serializers.Serializer):
 ...: something = serializers.DecimalField(decimal_places=4, max_digits=4)
 ...: 
In [52]: TestDecimal({"something": "0.100123"}).data # i know that there should be an object - added dict only to shorten the code
Out[52]: {'something': '0.1001'}
In [53]: TestDecimal({"something": "1.000"}).data
---------------------------------------------------------------------------
InvalidOperation Traceback (most recent call last)
Cell In[53], line 1
----> 1 TestDecimal({"something": "1.000"}).data
File /usr/local/lib/python3.10/site-packages/rest_framework/serializers.py:555, in Serializer.data(self)
 553 @property
 554 def data(self):
--> 555 ret = super().data
 556 return ReturnDict(ret, serializer=self)
File /usr/local/lib/python3.10/site-packages/rest_framework/serializers.py:253, in BaseSerializer.data(self)
 251 if not hasattr(self, '_data'):
 252 if self.instance is not None and not getattr(self, '_errors', None):
--> 253 self._data = self.to_representation(self.instance)
 254 elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
 255 self._data = self.to_representation(self.validated_data)
File /usr/local/lib/python3.10/site-packages/rest_framework/serializers.py:522, in Serializer.to_representation(self, instance)
 520 ret[field.field_name] = None
 521 else:
--> 522 ret[field.field_name] = field.to_representation(attribute)
 524 return ret
File /usr/local/lib/python3.10/site-packages/rest_framework/fields.py:1081, in DecimalField.to_representation(self, value)
 1078 if not isinstance(value, decimal.Decimal):
 1079 value = decimal.Decimal(str(value).strip())
-> 1081 quantized = self.quantize(value)
 1083 if not coerce_to_string:
 1084 return quantized
File /usr/local/lib/python3.10/site-packages/rest_framework/fields.py:1100, in DecimalField.quantize(self, value)
 1098 if self.max_digits is not None:
 1099 context.prec = self.max_digits
-> 1100 return value.quantize(
 1101 decimal.Decimal('.1') ** self.decimal_places,
 1102 rounding=self.rounding,
 1103 context=context
 1104 )
InvalidOperation: [<class 'decimal.InvalidOperation'>]
You must be logged in to vote

Replies: 1 comment 1 reply

Comment options

Facing same issue

You must be logged in to vote
1 reply
Comment options

Problem was size of number with decimals trimmed was > max_digits in serializer. Resolved by increasing max_digits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /