4

我们使用 django admin 作为面向客户端的后端,因此我们需要使其用户友好。我有一个模型,其中包含一组代表营养数据的 DecimalFields。

所有字段看起来像这样:

g_carbs = DecimalField(max_digits=13, decimal_places = 8, null=True, blank=True)

如果该字段留空,或者如果提供了非零值,则管理表单看起来和工作得很好。例如,对于像 10.5 这样的非空白、非零值,它会显示类似 的10.50000000内容,这很好。

问题是,对于任何 0 值,表单字段显示0E-8 的内容虽然在技术上是正确的,但不会为我的客户削减它,他们绝对不是科学家或工程师,并且不熟悉 E 表示法。

我没有使用自定义表单或任何自定义管理技巧。它正是 django 管理员为该模型自动渲染的内容。我正在考虑为此向 django 提交票证,但与此同时,我可以用自定义表单做些什么或解决这个问题吗?

4

3 回答 3

4

这就是最终对我有用的东西(到目前为止)。这既可以防止 E 表示法,也可以删除小数点后的尾随 0。

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)
于 2012-11-03T15:50:55.050 回答
1

一种简单的方法可能是继承 DecimalField 并更改其格式。

from django.db.models.fields import DecimalField

class NonscientificDecimalField(DecimalField):
    def format_number(self, value):
        """
        Overrides DecimalField's usual format_number by making sure 
        that the result is never in exponential notation for zero.
        """
        if value == 0:
            return "0.00000000"
        else:
            return super(DecimalField, self).format_number(value)

顺便说一句,您不应该将此作为 Django 错误提交 - 这是 Python 小数的工作方式,与 Django 几乎没有关系。打开一个shell并尝试str(Decimal("0.00000000")),你会看到Decimal('0E-8')

如果你想10.50000000显示为10.5,你可以调用normalize你的小数。这也将解决您的0E-8问题:

import decimal
from django.db.models.fields import DecimalField

class NonscientificDecimalField(DecimalField):
    def format_number(self, value):
        """
        Overrides DecimalField's usual format_number to remove trailing zeroes.
        """
        if isinstance(value, decimal.Decimal):
            context = decimal.Context(prec=self.max_digits)
            value = value.normalize(context=context)
        return super(DecimalField, self).format_number(value)
于 2012-10-31T18:53:20.533 回答
1

似乎已经修复了它:https ://code.djangoproject.com/ticket/19220但我不确定它是否完全有效,因为我使用的是 django 1.6.5 并且管理员显示0E-8.000000000E-8用于0.

models.DecimalField(max_digits=12, decimal_places=8, null=True)

@Ben Roberts:你还有问题吗?

谢谢

于 2014-09-02T14:12:29.307 回答