Reputation: 239988
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.
Upvotes: 202
Views: 211110
Reputation: 16671
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
Upvotes: 4
Reputation: 2776
Building on other answers, to extend this to floats, you can do:
{% load humanize %}
{{ floatvalue|floatformat:2|intcomma }}
Documentation: floatformat
, intcomma
.
Upvotes: 137
Reputation: 1727
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'
Upvotes: 39
Reputation: 4567
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}}
Upvotes: 67
Reputation: 2958
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.
Upvotes: 3
Reputation: 6299
Based on muhuk answer I did this simple tag encapsulating python string.format
method.
templatetags
at your's application folder. 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 format %}
{{ some_value|format:"{:0.2f}" }}
Upvotes: 5
Reputation: 375992
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.
Upvotes: 421
Reputation: 518
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.
Upvotes: 3
Reputation: 48555
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 %}
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.
Upvotes: 11
Reputation: 180
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)
Upvotes: 4
Reputation: 12895
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.
Upvotes: 1
Reputation: 16095
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.
Upvotes: 11
Reputation: 239988
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)
Upvotes: 2