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

126

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

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

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

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

  • 3
    Будьте осторожны, если ваши целевые пользователи также находятся в Европе. Некоторые европейские страны, такие как Германия, используют в качестве десятичного знака.
Теги:

13 ответов

240
Лучший ответ

Django Contributed humanize приложение делает это:

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

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

  • 13
    Есть ли причина, по которой эти несколько простых фильтров не являются частью встроенных фильтров?
  • 6
    встроена гуманизация - это часть джанго.
Показать ещё 3 комментария
89

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

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

Что касается решения Неда Батчелдера, то здесь оно с двумя десятичными знаками и знаком доллара. Это идет где-то как 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}}
  • 3
    Ошибка в приведенном выше коде, попробуйте это: >>> currency(0.99958) u'$0.00'
  • 1
    Спасибо @Ahsan. Исправлена.
Показать ещё 3 комментария
11

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

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)

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

9

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

USE_THOUSAND_SEPARATOR = True

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

Обратитесь к документации.


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

Есть также способ Python сделать это:

>>> '{:,}'.format(1000000)
'1,000,000'
  • 2
    Будьте осторожны при использовании этого. Также будет форматировать числа в URL и другие, которые вы добавляете в шаблон
  • 2
    Я не могу не подчеркнуть комментарий @Christoffer - в шаблонах, где идентификаторы отображаются и используются в ссылках, это может вызвать серьезные головные боли!
8

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

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

{% sexy_number some_variable %}

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

  • 1
    моя локаль - «pt_BR», а «intcomma» работает даже в Бразилии, где разделение - «.» а не ',' будучи floatvalue = 25000.35 {{floatvalue | intcomma}} приводит к 25000.35
  • 0
    Вы правы, но этот формат не подходит для разделителя тысяч (25 000,35 для en_US и 25 000,35 для fr_FR).
3

Слегка от темы:

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

$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 десятичными знаками, если это то, что вы хотите.

Возможно, немного на взломанной стороне, но, возможно, кому-то это будет полезно.

3

humanize app предлагает хороший и быстрый способ форматирования числа, но если вам нужно использовать разделитель, отличный от запятой, это просто просто повторно использовать код из приложения 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
    Благодарю. Мне нужна точечная версия, и ваше предложение спасло меня! Ура!
2

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

def format_price(self):
    import locale
    locale.setlocale(locale.LC_ALL, '')
    return locale.format('%d', self.price, True)
  • 0
    Хм - это было -1, без объяснения причин - бесполезно. Для тех, кто думает, что ответ в некотором роде неверен, пожалуйста, скажите почему для блага ответчика и читателей. Я полагаю, что я не являюсь поклонником установки языка (который является глобальным в пределах досягаемости), в этой единственной функции (неприятный побочный эффект получения валюты) - который может объяснить -1.
  • 0
    Я сделал второй -1 - как описано в пред. комментарий, это s really not correct not giving any reason. Here it просто: у Django есть специальный шаблон (похожий на Jinja2 - или Jinja2), который не поддерживает стандартные функции Python. Так что этот ответ бесполезен вообще. Более того, у Django есть собственные функции, управляющие этим и пишущие что-то новое, что работает, на самом деле не очень хорошая идея ...
Показать ещё 1 комментарий
1

На основе ответа 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}" }}
1

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

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

0

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

Тысяча сепараторов. Обязательно прочтите также локализацию формата.

0

Не знаю, почему это еще не упоминалось:

{% load l10n %}

{{ value|localize }}

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню