【问题标题】:Displaying a DecimalField with currency in the django admin在 django admin 中显示带有货币的 DecimalField
【发布时间】:2013-09-16 13:46:49
【问题描述】:

我有多个模型,其中多个 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) 

这是有道理的,但它阻止我在管理员中显示欧元符号/文本。

我该如何解决这个问题?

我知道我可以简单地对每个字段使用一种方法,将格式化的值显示为字符串,但我想知道是否有 DRYer 方式。

【问题讨论】:

    标签: python django django-admin decimal currency-formatting


    【解决方案1】:

    0.12 版本之前,django-money 货币表示部分支持 Django 管理员。

    自从0.12 版本(2017 年 10 月 22 日发布)以来,所有MoneyField 表示(包括 Django 的管理员)都可以使用特殊的formatter 进行配置。

    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
    )
    

    【讨论】:

      【解决方案2】:

      或者创建一个这样的类并从它继承

      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 %%'))
      

      【讨论】:

      • 我不再拥有代码库,但这看起来可能会起作用:S 我会在有时间测试它时尝试,以便我可以接受答案
      • 注意:在 python 3 中,basestring 仅更改为 strsuper(ImprovedAdmin, self).__init__(*args, **kwargs) 仅更改为 super().__init__(*args, **kwargs)
      【解决方案3】:

      为了在管理列表中显示,您可以在 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
      

      【讨论】:

      • 当然可以,但是我必须为每个字段制定一个方法。感觉不像是 DRY 解决方案
      • 您也可以在单独的行中添加formatted_amount.short_description = 'amount' 以修复列标题。
      • 此解决方案不支持在管理列表中排序值
      • @DataGreed 为了添加排序只需添加(基于上面的示例)formatted_amount.admin_order_field = "amount"
      猜你喜欢
      • 2017-07-01
      • 2012-08-12
      • 1970-01-01
      • 2020-05-13
      • 2011-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多