[Django]-Format numbers in django templates

414👍

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.

134👍

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

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

Documentation: floatformat, intcomma.

66👍

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

37👍

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'

11👍

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.

👤muhuk

10👍

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.

5👍

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

4👍

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)

4👍

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

From @Skratt’s comment:

In your settings file, make sure to add:

USE_L10N = True
USE_THOUSAND_SEPARATOR = True

3👍

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.

3👍

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.

2👍

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)
👤Oli

1👍

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.

👤zgoda

Leave a comment