Формат чисел в шаблонах django

Я пытаюсь отформатировать числа. Примеры:

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

это кажется довольно распространенной вещью, но я не могу понять, какой фильтр я должен использовать.

Edit: если у вас есть общий способ Python для этого, я рад добавить форматированное поле в свою модель.

13 ответов


Джанго вклад очеловечить приложение делает это:

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

обязательно добавьте 'django.contrib.humanize' на INSTALLED_APPS список .


основываясь на других ответах, чтобы распространить это на поплавки, вы можете сделать:

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

Что касается решения Неда Батчелдера, вот оно с 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}}

Если вы не хотите связываться с локалями, вот функция, которая форматирует числа:

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)

создание пользовательский шаблон фильтра из этой функции тривиально.


попробуйте добавить следующую строку в settings.py:

USE_THOUSAND_SEPARATOR = True

Это должно работать.

смотрите документация.


обновление в 2018-04-16:

существует также способ python сделать это:

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

на очеловечить решение хорошо, если ваш сайт на английском языке. Для других языков, вам нужно другое решение: я рекомендую использовать Бабель. Одним из решений является создание пользовательского тега шаблона для правильного отображения чисел. Вот как: просто создайте следующий файл в 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 %}
  • для американского пользователя (locale en_US) это отображает 1,234.56.
  • для французского пользователя (locale fr_FR)отображается 1 234,56.
  • ...

конечно, вы можете использовать переменные вместо:

{% sexy_number some_variable %}

Примечание: the context параметр в настоящее время не используется в моем примере, но я поместил его туда, чтобы показать, что вы можете легко настроить этот тег шаблона, чтобы он использовал все, что находится в контексте шаблона.


на очеловечить приложение предлагает хороший и быстрый способ форматирования числа, но если вам нужно использовать разделитель, отличный от запятой, просто повторно использовать код из приложения humanize, замените разделитель char и создать пользовательский фильтр. Например, используйте пробел в качестве разделителя:

@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)

немного не по теме:

Я нашел этот вопрос, ища способ форматирования числа в качестве валюты, например:

0
()  # 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:"-" }} отображать как .00 (С 2 десятичными знаками, если ты этого хочешь.

возможно, немного на хакерской стороне, но, возможно, кто-то еще найдет его полезным.


Ну, я не мог найти путь Django, но я нашел путь python изнутри моей модели:

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

следует учитывать, что изменение языка-это процесс и не потокобезопасными (в низине. могут иметь побочные эффекты или может повлиять на другой код выполняется в одном процессе).

мое предложение: проверить Бабель пакета. Некоторые средства интеграции с шаблонами Django доступны.


на основе muhuk ответа я сделал этот простой тег инкапсуляции в Python string.format метод.

  • создать templatetags в папке вашего приложения.
  • создать на нем.
  • добавьте к этому:

    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}" }}

Не уверен, почему это не было упомянуто, но:

{% load l10n %}

{{ value|localize }}

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

вы также можете использовать это в своем коде Django (внешние шаблоны), позвонив localize(number).


в случае, если кто-то наткнется на это, в Django 2.0.2 вы можете использовать этот

разделитель. Обязательно прочитайте формат локализация как хорошо.