Форматування чисел у шаблонах джанго


153

Я намагаюся відформатувати числа. Приклади:

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

Це здається досить поширеною справою, але я не можу зрозуміти, який фільтр я повинен використовувати.

Редагувати: Якщо у вас є загальний спосіб Python для цього, я радий додати форматне поле у ​​своїй моделі.


3
Будьте уважні, якщо цільові користувачі також перебувають у Європі. Деякі європейські країни, такі як Німеччина, використовують як десяткове позначення.
tobltobs

Відповіді:


313

Програма гуманізації Джанго робить це:

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

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


17
Чи є причина, чому ці кілька простих фільтрів не входять до вбудованих фільтрів?
PawelRoman

8
@PawelRoman Щоб уникнути завантаження групи фільтрів і тегів, які рідко використовуються (і тим самим зробити візуалізацію шаблону швидше)
Максим Лорант

Я додав "django.contrib.humanize" в INSTALLED_APPS і також включив {% load humanize%} у свій шаблон, а також перезапустив сервер. Однак, коли я намагаюся використовувати фільтр "intcomma", я отримую цю помилку - Недійсний фільтр: "intcomma" Слід налагодження показує "django.contrib.humanize", включений у settings.py. Що може бути можливою проблемою?
Маніш

1
Отримав тут відповідь на свою власну проблему - я включив {% load humanize%} у базовий шаблон (оскільки мені це потрібно для багатьох шаблонів). Здається, це не працює - коли я додав його у відповідні шаблони, він працював чудово! :-)
Manish

Якщо це не працює, це може бути пов’язано з локалізацією. Спробуйте {{my_num | intcomma: False}} у такому випадку
Хосе Черіан

105

Спираючись на інші відповіді, щоб поширити це на плавці, ви можете зробити:

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

Документація: floatformat, intcomma.


59

Що стосується рішення Неда Батчелдера, то воно з двома знаками після коми і знаком долара. Це іде десь так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'
Ahsan

1
Цей код повинен містити свій власний файл за адресою [your_project] / [your_app] / templatetags / [filtername] .py. Потім він повинен бути завантажений у шаблон із {% load [filtername]%}. Дивіться docs.djangoproject.com/en/1.10/howto/custom-template-tags для отримання більш корисної та конкретної інформації.
могучий

20

Спробуйте додати наступний рядок у settings.py:

USE_THOUSAND_SEPARATOR = True

Це має спрацювати.

Зверніться до документації .


оновлення на 2018-04-16:

Існує також пітон спосіб зробити це:

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

10
Будьте обережні, використовуючи це. Також буде форматувати номери в URL-адресах та інших, які ви додасте до шаблону
Крістофер

4
Я не можу підкреслити коментар @Christoffer досить - у шаблонах, де ідентифікатори відображаються та використовуються у посиланнях, це може спричинити великі головні болі!
LaundroMat

Це не підходить для шаблонів Джанго
Бен

@Ben, що не підходить? "шлях пітона" або прапор тисячі розділювачів у налаштуваннях? прапор роздільника тисяч повинен добре працювати для шаблонів Django. Яка версія вашого Django?
carton.swing

1
Формат рядка (python), тому що ви не можете використовувати це безпосередньо в шаблонах - вам доведеться помістити це в тег шаблону (що є прекрасною відповіддю), але просто викинути це не приносить користі як повноцінна відповідь.
Бен

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)

Створення користувальницького фільтра шаблонів за допомогою цієї функції тривіально.


10

Рішення гуманізувати чудово, якщо ваш веб-сайт англійською мовою. Для інших мов вам потрібно інше рішення: рекомендую використовувати 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 параметр в даний час не використовується в моєму прикладі, але я поклав його туди , щоб показати , що ви можете легко налаштувати цей шаблон тег , щоб зробити його використовувати що - небудь , що в контексті шаблону.


1
моя локаль - "pt_BR", а "intcomma" працює навіть у Бразилії, будучи поділом на "." а не по ',' будучи floatvalue = 25000.35 {{floatvalue | intcomma}} призводить до 25000.35
Zokis

Ви маєте рацію, але цей формат не підходить стосовно роздільника тисяч (25 000,35 для en_US та 25 000,35 для fr_FR).
MiniQuark

4

Додаток для гуманізації пропонує приємний та швидкий спосіб форматування числа, але якщо вам потрібно використовувати роздільник, який відрізняється від коми, просто просто використати код із програми гуманізації , замінити розділову таблицю та створити спеціальний фільтр . Наприклад, використовуйте простір як роздільник:

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

Дякую. Мені потрібна була крапка версія, і ваша пропозиція врятувала мене! Ура!
kstratis

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

Ну, я не зміг знайти шлях Джанго, але всередині своєї моделі я знайшов пітон:

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

Хм - це було -1'д, без жодних пояснень - недобре. Тим, хто вважає, що відповідь якимось чином невірний, будь ласка, скажіть, чому саме на користь відповідача та читачів. Я припускаю, що я не прихильник встановлення локальної точки (яка є загальнодоступною), в цій одній функції (неприємний побічний вплив на отримання валюти) - що могло б пояснити -1.
Danny Staple

Я зробив другий -1 - як описано в поперед. коментар, це s really not correct not giving any reason. Here itпросто: Django має специфічний шаблон (схожий на Jinja2 - або на Jinja2), який не дозволяє використовувати стандартні функції пітона. Тож ця відповідь зовсім не корисна. Більше того, у Джанго є власні функції управління цим і писати щось нове, що працює, насправді не гарна ідея ...
tomis

2
Я не погоджуюсь з погіршеннями - переконання, що значення належним чином відформатовано у функції перегляду до того, як воно потрапить у шаблон, видається ідеально правильним підходом.
Пол Томблін

1

Майте на увазі, що зміна локалі є загальнопроцессорною і не є безпечною для потоків (іо., Може мати побічні ефекти або впливати на інший код, виконаний у межах одного процесу).

Моя пропозиція: ознайомтеся з пакетом Babel . Існують деякі засоби інтеграції з шаблонами Django.



1

На основі відповіді muhuk я зробив цей простий string.formatметод інкапсуляції тегів python .

  • Створіть 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}" }}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.