Reputation: 172
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
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