我的DecimalField上不一致出现尾随零
我想用一个DecimalField
来处理小数,要求有6位小数,现在我在一个独立的模型里测试这个功能:
class MyItem(models.Model):
myval = models.DecimalField(max_digits=18, decimal_places=6)
def __str__(self):
return str(self.myval)
目前我在使用内置的管理界面,观察到以下情况:
- 输入最多4位小数的值(比如0.0001)是正常的
- 输入大于1的值也没问题
但是,像0.00001
或0.000001
这样的值会显示成带有尾随零的形式,也就是0.000010
。
虽然从数学上讲这是正确的(数字是一样的),而且我可以通过一些小操作去掉这个零,但我觉得有点困扰,因为有时候这个零会出现,有时候又不会。我也没有测试过很多不同的数字,所以不确定所有数字的正确值是否真的会被保存。
根据我的理解,DecimalField
应该是保持精确的。我在创建模型时是不是漏掉了什么基本的东西?这是怎么回事呢?
我使用的版本是Python 3.3和Django 1.6
1 个回答
1
这里有一个对DecimalField模型的重写,应该能解决这个问题,具体内容可以在这里找到:
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)