I have a Django Rest Framework serializer with a DecimalField
serializers.DecimalField(max_digits=9, decimal_places=6)
Now if I try to deserialize data that contains a decimal with a higher precision (i.e. 50.1234567) the serializer raises a ValidationError:
"Ensure that there are no more than 6 decimal places."
This even happens if the last digit is 0. Is it possible to make the serializer round the given value to the maximum precision (i.e. 50.1234567 to 50.123457)? And if so how?
After coercing the input to a Decimal the DecimalField validates the precision of the value in the aptly named, but undocumented, validate_precision
method. So to disable this validation one can override this method and simply return the input value:
class RoundingDecimalField(serializers.DecimalField):
def validate_precision(self, value):
return value
It turns out that doing this is enough to get the desired rounding behaviour.
After calling validate_precision
the DecimalField calls quantize
which will "Quantize the decimal value to the configured precision" (from the docstring).
The rounding mode for this quantisation process is controlled by the current active decimal context.
If a specific rounding mode is desired one can use the (again undocumented) drf_braces.fields.custom.RoundedDecimalField
field from django-rest-framework-braces. This field takes an optional rounding argument where one can specify the desired rounding mode.
Appreciate the answer, @jaap3. Wanted to add my implementation here for reference for others who find this question. Here's how I used this rounding field inside another serializer class with an attribute I wanted rounded to the max_digits value set on the Position model.
class RoundingDecimalField(serializers.DecimalField):
"""Used to automaticaly round decimals to the model's accepted value."""
def validate_precision(self, value):
return value
class PositionSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='target_position-detail')
price = RoundingDecimalField(max_digits=21, decimal_places=14)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With