Tina Vall
Tina Vall

Reputation: 172

A trailing zero appears inconsistently on my DecimalField

I want to use a DecimalField with 6 decimal places and am testing it in a standalone model:

class MyItem(models.Model):
    myval = models.DecimalField(max_digits=18, decimal_places=6)
    def __str__(self):
        return str(self.myval)

Right now I am using it with the built-in admin, and observe the following:

But, adding values like 0.00001 or 0.000001 will display it with a trailing zero, that is, 0.000010.

While it is mathematically correct (the same number), and I could trim the zero with little work, I am bothered that sometimes this zero appears and other times, it does not. I also haven't tested a very wide range of numbers, and am not sure if the correct value will really be saved for all numbers.

As I understand, DecimalField is supposed to preserve exactness. Am I missing something basic in creating the model? What is going on?

Versions used are Python 3.3 and Django 1.6

Upvotes: 1

Views: 714

Answers (1)

Chris Montanaro
Chris Montanaro

Reputation: 18192

Here's an override of the DecimalField model that should solve the issue, found here:

class NonscientificDecimalField(DecimalField):
    """ Prevents values from being displayed with E notation, with trailing 0's
        after the decimal place  truncated. (This causes precision to be lost in
        many cases, but is more user friendly and consistent for non-scientist
        users)
    """
    def value_from_object(self, obj):
        def remove_exponent(val):
            """Remove exponent and trailing zeros.
               >>> remove_exponent(Decimal('5E+3'))
               Decimal('5000')
            """
            context = decimal.Context(prec=self.max_digits)
            return val.quantize(decimal.Decimal(1), context=context) if val == val.to_integral() else val.normalize(context)

        val = super(NonscientificDecimalField, self).value_from_object(obj)
        if isinstance(val, decimal.Decimal):
            return remove_exponent(val)

Upvotes: 1

Related Questions