Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to round to zero decimals if there is no decimal value with Jinja2?

I building a website using the (excellent) Flask framework in which I now want to display some numbers. The round filter provided by jinja2 works fine, except for when there is no decimal value:

{{ 1.55555|round(2) }} -> 1.56
{{ 1.5|round(2) }} -> 1.5
{{ 1.0|round(2) }} -> 1.0
{{ 1|round(2) }} -> 1.0

But I want the last two to be displayed like 1 (without a trailing .0). Does anybody know how I can do this with jinja2? All tips are welcome!

[EDIT]

I tried using trim(), but to my surprise the snippet below gives a TypeError: do_trim() takes exactly 1 argument (2 given):

{{ 1.0|round(2)|trim('.0') }}
like image 936
kramer65 Avatar asked Dec 09 '22 04:12

kramer65


2 Answers

You can use string filter, then use str.rstrip:

>>> import jinja2
>>> print(jinja2.Template('''
... {{ (1.55555|round(2)|string).rstrip('.0') }}
... {{ (1.5|round(2)|string).rstrip('.0') }}
... {{ (1.0|round(2)|string).rstrip('.0') }}
... {{ (1|round(2)|string).rstrip('.0') }}
... ''').render())

1.56
1.5
1
1

NOTE

Using str.rstrip, you will get an empty string for 0.

>>> jinja2.Template('''{{ (0|round(2)|string()).strip('.0') }}''').render()
u''

Here's a solution to avoid above (call rstrip twice; once with 0, once with .)

>>> print(jinja2.Template('''
... {{ (1.55555|round(2)|string).rstrip('0').rstrip('.') }}
... {{ (1.5|round(2)|string).rstrip('0').rstrip('.') }}
... {{ (1.0|round(2)|string).rstrip('0').rstrip('.') }}
... {{ (1|round(2)|string).rstrip('0').rstrip('.') }}
... {{ (0|round(2)|string).rstrip('0').rstrip('.') }}
... ''').render())

1.56
1.5
1
1
0

UPDATE Above codes will trim 10 to 1. Following code does not have the issue. using format filter.

>>> print(jinja2.Template('''
... {{ ("%.2f"|format(1.55555)).rstrip('0').rstrip('.') }}
... {{ ("%.2f"|format(1.5)).rstrip('0').rstrip('.') }}
... {{ ("%.2f"|format(1.5)).rstrip('0').rstrip('.') }}
... {{ ("%.2f"|format(1.0)).rstrip('0').rstrip('.') }}
... {{ ("%.2f"|format(0)).rstrip('0').rstrip('.') }}
... {{ ("%.2f"|format(10)).rstrip('0').rstrip('.') }}
... ''').render())

1.56
1.5
1.5
1
0
10
like image 200
falsetru Avatar answered Dec 11 '22 09:12

falsetru


If you're going to use this a lot, I think it's best to write a custom filter to avoid clutter, like this:

from jinja2 import filters

def myround(*args, **kw):
    # Use the original round filter, to deal with the extra arguments
    res = filters.do_round(*args, **kw)
    # Test if the result is equivalent to an integer and
    # return depending on it
    ires = int(res)
    return (res if res != ires else ires)

Register it, and you're done. Example in the interactive interpreter:

>>> from jinja2 import Environment
>>> env = Environment()
>>> env.filters['myround'] = myround
>>> env.from_string("{{ 1.4|myround(2) }}").render()
u'1.4'
>>> env.from_string("{{ 1.4|myround }}").render()
u'1'
>>> env.from_string("{{ 0.3|myround }}").render()
u'0'
like image 34
Ricardo Cárdenes Avatar answered Dec 11 '22 09:12

Ricardo Cárdenes