55

I'm trying to format a float as comma-separated currency. E.g. 543921.9354 becomes $543,921.94. I'm using the format filter in Jinja templates, which seems to mimic the % operator in Python rather than the Python format function?

How can I accomplish this formatting in Jinja? Is it possible using the format filter? This is what I have so far, which accomplishes everything except the commas:

"$%.2f"|format(543921.9354)

which of course yields

$543921.94

Kyle Johnson
  • 1,605
  • 2
  • 17
  • 26

6 Answers6

101

Update: Using Jinja2 and Python 3, this worked quite nicely in the template without having to define any custom code:

{{ "${:,.2f}".format(543921.9354) }}

I'm not sure exactly what the dependencies are to have this work, but IMHO anyone else reading this answer would do well to at least try it before worrying about custom filters.

Nathan Osman
  • 71,149
  • 71
  • 256
  • 361
biomiker
  • 3,108
  • 1
  • 29
  • 26
  • 2
    This is working for me on Python 2.7 as well. Great answer! – hamx0r Feb 16 '16 at 18:35
  • any idea on how to hide the round part and only display decimals? – Alexandru R May 06 '16 at 08:37
  • Works Great!! One downside is for negative numbers the sign is after the $. Ex: -1000.50 = $-1,000.50. I was able to solve this by writing a custom filter using babel – Ravishankar Sivasubramaniam Apr 10 '19 at 01:30
  • Good point Ravishankar. I don't have Jinja2 at my fingertips anymore but I wonder if something like this would work? {{ n >= 0 ? "${:,.2f}".format(n) : "-${:,.2f}".format(abs(n)) }} Let us know if you can try it. :) – biomiker Apr 11 '19 at 17:07
54

Write a custom filter for that. If you are using python 2.7, it can look like this:

def format_currency(value):
    return "${:,.2f}".format(value)
alex vasi
  • 5,304
  • 28
  • 31
14

Python3.6:

def numberFormat(value):
    return format(int(value), ',d')

Flask global filter

@app.template_filter()
def numberFormat(value):
    return format(int(value), ',d')

Flask global filter for Blueprint

@app.app_template_filter()
def numberFormat(value):
    return format(int(value), ',d')

Call this global filter

{{ '1234567' | numberFormat }}
#prints 1,234,567

Calling it in Jinja without assigning a global filter

{{ format('1234567', ',d') }}
#prints 1,234,567
Yongju Lee
  • 241
  • 4
  • 5
7

To extend @alex vasi's answer, I would definitely write a custom filter, but I'd also use python's own locale functionality, which handles currency grouping, and the symbol,

def format_currency(value):
    return locale.currency(value, symbol=True, grouping=True)

The main thing to take note of using locale is that it doesn't work with the default 'C' locale, so you have to set it so something that's available on your machine.

For what you're looking for, you probably need,

locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')

but if you wanted sterling pounds, you'd use,

locale.setlocale(locale.LC_ALL, 'en_GB.UTF_8')

.

import locale
locale.setlocale(locale.LC_ALL, 'en_US')
locale.currency(543921.94, symbol=True, grouping=True)
> '$543,921.94'
locale.setlocale(locale.LC_ALL, 'en_GB')
> '£543,921.94'
Lance
  • 399
  • 1
  • 5
  • 14
seaders
  • 3,878
  • 3
  • 40
  • 64
3

If you have Python 2.6 or newer:

You could write a custom filter for one purpose, but, as a broader solution, you could also update the format filter itself:

from jinja import Environment, FileSystemLoader

def format(fmt_str, *args, **kwargs):
    if args and kwargs:
        raise jinja2.exceptions.FilterArgumentError(
            "can't handle positional and keyword "
            "arguments at the same time"
        )
    ufmt_str = jinja2.utils.soft_unicode(fmt_str)
    if kwargs:
        return ufmt_str.format(**kwargs)
    return ufmt_str.format(*args)


env = Environment(loader=FileSystemLoader('./my/template/dir'))
env.filters.update({
    'format': format,
})

This will replace the existing format filter (as of Jinja 2.7.1). The majority of the function was ripped straight from the format source. The only difference between this function and jinja's is that it uses the str.format() function to format the string.

Seeing that Jinja2 (at the time of this writing) no longer supports Python 2.5, I bet it won't be long before the format filter uses Python's str.format().

OozeMeister
  • 4,638
  • 1
  • 23
  • 31
3

Custom Filter using Babel (Can be used to format other currencies as well)

Install Babel (http://babel.pocoo.org/en/latest/api/numbers.html)

pip install Babel

Custom Jinja Filter

from babel.numbers import format_currency

@app.template_filter()
def usdollar(value):
   return format_currency(value, 'USD', locale='en_US')

app.jinja_env.filters['usdollar'] = usdollar

Usage in Jinja Template:

{{ '-10000.500' | usdollar }}

Output : -$10,000.50