pythonpython-3.xdjangodecimal

Python Set Context precision for Decimal field


from decimal import Decimal, setcontext, getcontext

class MyNewSerializer(serializers.Serializer):
    total_value_base = serializers.SerializerMethodField()
    total_outgoing_value_base = serializers.DecimalField(
        max_digits=38,
        decimal_places=8,
        source="value_sent",
    )
    total_incoming_value = serializers.DecimalField(
        max_digits=38,
        decimal_places=4,
        source="value_received",
    )

    def get_total_value_base(self, obj):
        total = Decimal(obj.value_received) + Decimal(
            obj.value_sent
        )
        # Values of above objects
        # obj.value_received = 425933085766969760747388.45622168 
        # obj.value_sent = 0
        # total = 425933085766969760747388.4562  

        dec = Decimal(str(total))
        return round(dec, 8)

But this is throwing error:

return round(dec, 8)
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]

This get's fixed when i do the following:

def get_total_value_base(self, obj):
        # the below line fixes the issue
        getcontext().prec = 100
        
        total = Decimal(obj.value_received) + Decimal(
            obj.value_sent
        )
        # Values of above objects
        # obj.value_received = 425933085766969760747388.45622168 
        # obj.value_sent = 0
        # total = 425933085766969760747388.4562  

        dec = Decimal(str(total))
        return round(dec, 8)

I want to increase precision for all the values in the class as well as other similar classes.

How can i do that using a base class or overriding the Decimal class for the whole file or for various classes in the file?

I am expecting to increase the decimal precision for 100's of variables that are present in a file in various different classes.


Solution

  • It can be done in the following way:

    from decimal import Decimal, getcontext
    
    class HighDecimalPrecision:
        def __getattribute__(self, name):
            # Set the precision for Decimal operations
            getcontext().prec = 100
            return super().__getattribute__(name)
    
    class MyNewSerializer(HighDecimalPrecision, serializers.Serializer):
        ...