在django admin中显示带有货币的DecimalField

eiee3dmh  于 2023-01-22  发布在  Go
关注(0)|答案(4)|浏览(125)

我有多个模型与多个DecimalField代表金钱,如100.34欧元。
我的目标是在管理员列表视图中显示货币,如下图所示。
http://i.imgur.com/XKEQFp9.png
然而,我无法找到一种方法来做到这一点,为每一个金钱领域。
我试着创建一个自定义的MoneyField,继承DecimalField并修改unicode表示,但它不起作用。
我也尝试了https://github.com/jakewins/django-money,但没有运气。
我研究了django admin的源代码,终于发现了问题:
在django.admin.contrib.admin.util.py的display_for_field函数中,它检查值是否是DecimalField的示例,如果是,它将其显示为十进制数。

elif isinstance(field, models.DecimalField):
    return formats.number_format(value, field.decimal_places)

这是有道理的,但它阻止我在管理中显示欧元符号/文本。
我怎样才能解决这个问题?
我知道我可以简单地对每个字段使用一个方法,将格式化的值显示为字符串,但我想知道是否有更干燥的方法。

2wnc66cl

2wnc66cl1#

要在admin列表中显示,可以在ModelAdmin类中创建一个自定义函数,调用该函数来格式化每个值:

class MyModelAdmin(admin.ModelAdmin):
    list_display = ('formatted_amount', ...other fields...,)

    def formatted_amount(self, obj):
        # obj is the Model instance

        # If your locale is properly set, try also:
        # locale.currency(obj.amount, grouping=True)
        return '%.2f EUR' % obj.amount
w6lpcovy

w6lpcovy2#

或者创建这样的类并从其继承

class ImprovedAdmin(admin.ModelAdmin):
    """Handles column formatting in list display"""
    def __init__(self, *args, **kwargs):
        def generate_formatter(name, str_format):
            formatter = lambda o: str_format%(getattr(o, name) or 0)
            formatter.short_description = name
            formatter.admin_order_field = name
            return formatter

        all_fields = []
        for f in self.list_display:
            if isinstance(f, basestring):
                all_fields.append(f)
            else:
                new_field_name = f[0]+'_formatted'
                setattr(self, new_field_name, generate_formatter(f[0], f[1]))
                all_fields.append(new_field_name)
        self.list_display = all_fields

        super(ImprovedAdmin, self).__init__(*args, **kwargs)

class MyModelAdmin(ImprovedAdmin):
    list_display = ('id', ('amount', '%.2f EUR'), ('interest', '%.2f %%'))
yebdmbv4

yebdmbv43#

有两种方式可以显示**“34.00 EUR”,这样,即使小数位为零**,您也可以始终显示带有第二个小数位的数字。

〈第一条路〉

用models.DecimalField和decimal_places=2定义price,如下所示:

# "models.py"

from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField(
        max_digits=5,
        decimal_places=2, # Here
        validators=[
            MaxValueValidator(99999),
            MinValueValidator(0)
        ],
        default=0
    )

然后,定义price_with_EUR()并将其分配给list_display,如下所示:

# "admin.py"

from django.contrib import admin
from .models import Product

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = [
        'name', 
        'price_with_EUR' # Here
    ]

    def price_with_EUR(self, obj): # Here
        return f'{self.price} EUR'

〈第二条路〉

使用**@property装饰器定义price_with_EUR(),如下所示”models.py“**。

”models.py“

from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        validators=[
            MaxValueValidator(99999),
            MinValueValidator(0)
        ],
        default=0
    )

    @property # Here
    def price_with_EUR(self):
        return f'{self.price} EUR'

然后,将price_with_EUR()赋值给list_display,如下所示:

# "admin.py"

from django.contrib import admin
from .models import Product

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = [
        'name', 
        'price_with_EUR' # Here
xnifntxz

xnifntxz4#

0.12版本之前,Django管理员部分支持django-money货币表示。
0.12版本(2017年10月22日发布)起,所有MoneyField表示(包括Django的admin)都可以配置特殊的格式化程序。

import moneyed
from moneyed.localization import _FORMATTER
from decimal import ROUND_HALF_EVEN

BOB = moneyed.add_currency(
    code='BOB',
    numeric='068',
    name='Peso boliviano',
    countries=('BOLIVIA', )
)

# Currency Formatter will output 2.000,00 Bs.
_FORMATTER.add_sign_definition(
    'default',
    BOB,
    prefix=u'Bs. '
)

_FORMATTER.add_formatting_definition(
    'es_BO',
    group_size=3, group_separator=".", decimal_point=",",
    positive_sign="",  trailing_positive_sign="",
    negative_sign="-", trailing_negative_sign="",
    rounding_method=ROUND_HALF_EVEN
)

相关问题