在Django模板中格式化数字

问题:在Django模板中格式化数字

我正在尝试格式化数字。例子:

1     => 1
12    => 12
123   => 123
1234  => 1,234
12345 => 12,345

它很常见,但是我无法弄清楚应该使用哪个过滤器。

编辑:如果您有通用的Python方法可以执行此操作,则很高兴在模型中添加格式化的字段。

I’m trying to format numbers. Examples:

1     => 1
12    => 12
123   => 123
1234  => 1,234
12345 => 12,345

It strikes as a fairly common thing to do but I can’t figure out which filter I’m supposed to use.

Edit: If you’ve a generic Python way to do this, I’m happy adding a formatted field in my model.


回答 0

Django的贡献人性化应用程序执行以下操作:

{% load humanize %}
{{ my_num|intcomma }}

确保将文件添加'django.contrib.humanize'INSTALLED_APPS列表中settings.py

Django’s contributed humanize application does this:

{% load humanize %}
{{ my_num|intcomma }}

Be sure to add 'django.contrib.humanize' to your INSTALLED_APPS list in the settings.py file.


回答 1

在其他答案的基础上,要将其扩展到浮点数,可以执行以下操作:

{% load humanize %}
{{ floatvalue|floatformat:2|intcomma }}

文档:floatformatintcomma

Building on other answers, to extend this to floats, you can do:

{% load humanize %}
{{ floatvalue|floatformat:2|intcomma }}

Documentation: floatformat, intcomma.


回答 2

关于Ned Batchelder的解决方案,此处为2个小数点和一个美元符号。这就像my_app/templatetags/my_filters.py

from django import template
from django.contrib.humanize.templatetags.humanize import intcomma

register = template.Library()

def currency(dollars):
    dollars = round(float(dollars), 2)
    return "$%s%s" % (intcomma(int(dollars)), ("%0.2f" % dollars)[-3:])

register.filter('currency', currency)

那么你就可以

{% load my_filters %}
{{my_dollars | currency}}

Regarding Ned Batchelder’s solution, here it is with 2 decimal points and a dollar sign. This goes somewhere like my_app/templatetags/my_filters.py

from django import template
from django.contrib.humanize.templatetags.humanize import intcomma

register = template.Library()

def currency(dollars):
    dollars = round(float(dollars), 2)
    return "$%s%s" % (intcomma(int(dollars)), ("%0.2f" % dollars)[-3:])

register.filter('currency', currency)

Then you can

{% load my_filters %}
{{my_dollars | currency}}

回答 3

尝试在settings.py中添加以下行:

USE_THOUSAND_SEPARATOR = True

这应该工作。

请参阅文档


更新于2018-04-16:

还有一种执行此操作的python方法:

>>> '{:,}'.format(1000000)
'1,000,000'

Try adding the following line in settings.py:

USE_THOUSAND_SEPARATOR = True

This should work.

Refer to documentation.


update at 2018-04-16:

There is also a python way to do this thing:

>>> '{:,}'.format(1000000)
'1,000,000'

回答 4

如果您不想参与语言环境,则可以使用以下函数来格式化数字:

def int_format(value, decimal_points=3, seperator=u'.'):
    value = str(value)
    if len(value) <= decimal_points:
        return value
    # say here we have value = '12345' and the default params above
    parts = []
    while value:
        parts.append(value[-decimal_points:])
        value = value[:-decimal_points]
    # now we should have parts = ['345', '12']
    parts.reverse()
    # and the return value should be u'12.345'
    return seperator.join(parts)

从此函数创建自定义模板过滤器很简单。

If you don’t want to get involved with locales here is a function that formats numbers:

def int_format(value, decimal_points=3, seperator=u'.'):
    value = str(value)
    if len(value) <= decimal_points:
        return value
    # say here we have value = '12345' and the default params above
    parts = []
    while value:
        parts.append(value[-decimal_points:])
        value = value[:-decimal_points]
    # now we should have parts = ['345', '12']
    parts.reverse()
    # and the return value should be u'12.345'
    return seperator.join(parts)

Creating a custom template filter from this function is trivial.


回答 5

人文化的解决方案是好的,如果你的网站是英文的。对于其他语言,您需要另一种解决方案:我建议使用Babel。一种解决方案是创建一个自定义模板标签以正确显示数字。方法如下:只需在中创建以下文件your_project/your_app/templatetags/sexify.py

# -*- coding: utf-8 -*-
from django import template
from django.utils.translation import to_locale, get_language
from babel.numbers import format_number

register = template.Library()

def sexy_number(context, number, locale = None):
    if locale is None:
        locale = to_locale(get_language())
    return format_number(number, locale = locale)

register.simple_tag(takes_context=True)(sexy_number)

然后,您可以像下面这样在模板中使用此模板标记:

{% load sexy_number from sexify %}

{% sexy_number 1234.56 %}
  • 对于美国用户(语言环境为en_US),显示为1,234.56。
  • 对于法语用户(语言环境fr_FR),这将显示1 234,56。

当然,您可以改用变量:

{% sexy_number some_variable %}

注意:context参数当前未在我的示例中使用,但我将其放在此处表明您可以轻松地调整此模板标签以使其使用模板上下文中的任何内容。

The humanize solution is fine if your website is in English. For other languages, you need another solution: I recommend using Babel. One solution is to create a custom template tag to display numbers properly. Here’s how: just create the following file in your_project/your_app/templatetags/sexify.py:

# -*- coding: utf-8 -*-
from django import template
from django.utils.translation import to_locale, get_language
from babel.numbers import format_number

register = template.Library()

def sexy_number(context, number, locale = None):
    if locale is None:
        locale = to_locale(get_language())
    return format_number(number, locale = locale)

register.simple_tag(takes_context=True)(sexy_number)

Then you can use this template tag in your templates like this:

{% load sexy_number from sexify %}

{% sexy_number 1234.56 %}
  • For an american user (locale en_US) this displays 1,234.56.
  • For a french user (locale fr_FR), this displays 1 234,56.

Of course you can use variables instead:

{% sexy_number some_variable %}

Note: the context parameter is currently not used in my example, but I put it there to show that you can easily tweak this template tag to make it use anything that’s in the template context.


回答 6

人文化的应用程序提供了一个很好和格式化号码的快捷方式,但如果你需要使用一个分离器不同于逗号,它的简单,只是重复使用从人文化的应用程序的代码,则更换分隔字符,并创建一个自定义过滤器。例如,使用空格作为分隔符:

@register.filter('intspace')
def intspace(value):
    """
    Converts an integer to a string containing spaces every three digits.
    For example, 3000 becomes '3 000' and 45000 becomes '45 000'.
    See django.contrib.humanize app
    """
    orig = force_unicode(value)
    new = re.sub("^(-?\d+)(\d{3})", '\g<1> \g<2>', orig)
    if orig == new:
        return new
    else:
        return intspace(new)

The humanize app offers a nice and a quick way of formatting a number but if you need to use a separator different from the comma, it’s simple to just reuse the code from the humanize app, replace the separator char, and create a custom filter. For example, use space as a separator:

@register.filter('intspace')
def intspace(value):
    """
    Converts an integer to a string containing spaces every three digits.
    For example, 3000 becomes '3 000' and 45000 becomes '45 000'.
    See django.contrib.humanize app
    """
    orig = force_unicode(value)
    new = re.sub("^(-?\d+)(\d{3})", '\g<1> \g<2>', orig)
    if orig == new:
        return new
    else:
        return intspace(new)

回答 7

稍微偏离主题:

我在寻找一种将数字格式化为货币的方法时发现了这个问题,如下所示:

$100
($50)  # negative numbers without '-' and in parens

我最终做了:

{% if   var >= 0 %} ${{ var|stringformat:"d" }}
{% elif var <  0 %} $({{ var|stringformat:"d"|cut:"-" }})
{% endif %}

您也可以这样做,例如{{ var|stringformat:"1.2f"|cut:"-" }}显示为$50.00(如果要的话, 2位小数。

也许稍微有点怪癖,但也许其他人会发现它很有用。

Slightly off topic:

I found this question while looking for a way to format a number as currency, like so:

$100
($50)  # negative numbers without '-' and in parens

I ended up doing:

{% if   var >= 0 %} ${{ var|stringformat:"d" }}
{% elif var <  0 %} $({{ var|stringformat:"d"|cut:"-" }})
{% endif %}

You could also do, e.g. {{ var|stringformat:"1.2f"|cut:"-" }} to display as $50.00 (with 2 decimal places if that’s what you want.

Perhaps slightly on the hacky side, but maybe someone else will find it useful.


回答 8

好吧,我找不到Django方式,但确实从模型内部找到了python方式:

def format_price(self):
    import locale
    locale.setlocale(locale.LC_ALL, '')
    return locale.format('%d', self.price, True)

Well I couldn’t find a Django way, but I did find a python way from inside my model:

def format_price(self):
    import locale
    locale.setlocale(locale.LC_ALL, '')
    return locale.format('%d', self.price, True)

回答 9

请注意,更改区域设置是在整个进程范围内进行的,并且不是线程安全的(现在,可能会有副作用,或者可能影响在同一进程中执行的其他代码)。

我的主张:检查Babel软件包。提供了一些与Django模板集成的方法。

Be aware that changing locale is process-wide and not thread safe (iow., can have side effects or can affect other code executed within the same process).

My proposition: check out the Babel package. Some means of integrating with Django templates are available.


回答 10

不知道为什么还没有提到:

{% load l10n %}

{{ value|localize }}

https://docs.djangoproject.com/zh-CN/1.11/topics/i18n/formatting/#std:templatefilter-localize

您还可以通过调用在Django代码(外部模板)中使用此代码localize(number)

Not sure why this has not been mentioned, yet:

{% load l10n %}

{{ value|localize }}

https://docs.djangoproject.com/en/1.11/topics/i18n/formatting/#std:templatefilter-localize

You can also use this in your Django code (outside templates) by calling localize(number).


回答 11

基于muhuk的答案,我做了这个简单的标记封装python string.format方法。

  • 创建一个 templatetags在您的应用程序文件夹中。
  • format.py在其上创建一个文件。
  • 添加到它:

    from django import template
    
    register = template.Library()
    
    @register.filter(name='format')
    def format(value, fmt):
        return fmt.format(value)
  • 将其加载到模板中 {% load format %}
  • 用它。 {{ some_value|format:"{:0.2f}" }}

Based on muhuk answer I did this simple tag encapsulating python string.format method.

  • Create a templatetags at your’s application folder.
  • Create a format.py file on it.
  • Add this to it:

    from django import template
    
    register = template.Library()
    
    @register.filter(name='format')
    def format(value, fmt):
        return fmt.format(value)
    
  • Load it in your template {% load format %}
  • Use it. {{ some_value|format:"{:0.2f}" }}

回答 12

万一有人偶然发现了这个,Django 2.0.2你可以用这个

千位分隔符。确保还阅读格式本地化

In case someone stumbles upon this, in Django 2.0.2 you can use this

Thousand separator. Be sure to read format localization as well.