70

How do I persuade Jinja2 to not print "None" when the value is None?

I have a number of entries in a dictionary and I would like to output everything in a single loop instead of having special cases for different keywords. If I have a value of None (the NoneType not the string) then the string "None" is inserted into the template rendering results.

Trying to suppress it using {{ value or '' }} works too well as it will replace the numeric value zero as well.

Do I need to filter the dictionary before passing it to Jinja2 for rendering?

1
  • 1
    Is there any way to do it without interfering with the template?
    – lajarre
    Commented Apr 14, 2015 at 15:41

6 Answers 6

80

In new versions of Jinja2 (2.9+):

{{ value if value }}

In older versions of Jinja2 (prior to 2.9):

{{ value if value is not none }} works great.

if this raises an error about not having an else try using an else ..

{{ value if value is not none else '' }}

5
  • 1
    I got an error with this: UndefinedError: the inline if-expression evaluated to false and no else section was defined. Commented Jun 10, 2014 at 11:26
  • 4
    {{ value if value != None else '' }} may be necessary to avoid the problem @GeenHenk had
    – robo
    Commented Apr 14, 2015 at 20:12
  • 4
    I think is not None instead of != None should be used.
    – warvariuc
    Commented Aug 5, 2015 at 6:04
  • 7
    Today this just gives me TemplateAssertionError: no test named 'None'
    – Kylotan
    Commented Mar 20, 2016 at 18:35
  • 5
    As of 2017 (Jinja 2.9), you just need {{ value if value }}. No need of comparing to None.
    – cjlallana
    Commented Oct 23, 2017 at 12:00
37

Another option is to use the finalize hook on the environment:

>>> import jinja2
>>> e = jinja2.Environment()
>>> e.from_string("{{ this }} / {{ that }}").render(this=0, that=None)
u'0 / None'

but:

>>> def my_finalize(thing):
...     return thing if thing is not None else ''
...
>>> e = jinja2.Environment(finalize=my_finalize)
>>> e.from_string("{{ this }} / {{ that }}").render(this=0, that=None)
u'0 / '
2
  • I think this is the smartest way to do it. However, when I tried this method with FastAPI's jinja2, url_for() in the template stopped working. For your information.
    – mitsu
    Commented Dec 22, 2021 at 4:28
  • this works great, thank you. to plug it into a flask app in one line, you can use app.jinja_options['finalize'] = lambda x: x if x is not None else ''. You can just put that right under app = Flask(__name__) Commented Jun 11 at 20:58
30

Default filter:

{{ value|default("", True) }}
4
  • 1
    this has the same problem as OP's main solution... I think this would work as {{ value|default("", True ) }} Commented Jun 21, 2012 at 21:39
  • 1
    Without the True, this doesn't work at all. With the True, it replaces the None and the numeric zero .. so no good.
    – Spaceghost
    Commented Jun 21, 2012 at 21:42
  • You are right, it only works when the variable isn't defined instead of assigning None to it. But writing a filter for the None case would be worth it just for being less verbose than the chosen answer.
    – solarc
    Commented Jun 21, 2012 at 23:07
  • 1
    I like this solution the best.
    – corvid
    Commented Aug 12, 2014 at 1:08
23

According to this post from the Pocco Mailing List: https://groups.google.com/d/msg/pocoo-libs/SQ9ubo_Kamw/TadIdab9eN8J

Armin Ronacher (creater of Jinja2/Flask, etc...) recommends the following "pythonic" snippet:

{{ variable or 0 }} {{ variable or '' }}

The notion here being that once again, explicit is preferable to implicit.

Edit: The selected answer is definitely the correct one. I haven't really come across a situation where a template variable would be either a string or the numeric zero, so the above snippets might help reduce the code noise in the template.

1
  • It was noted in the question that this does not help because it also suppresses numeric zero
    – Spaceghost
    Commented Oct 23, 2014 at 21:34
23

A custom filter can solve the problem. Declare it like this:

def filter_suppress_none(val):
    if not val is None:
        return val
    else:
        return ''

Install it like this:

templating_environment.filters['sn'] = filter_suppress_none

Use it like this:

{{value|sn}}
3
  • 2
    Possibly the most elegant solution here. Jinja could have a filter like this, maybe with less cryptic name than "sn" :)
    – Peter Lada
    Commented Jul 2, 2014 at 3:27
  • 2
    Great answer. One nitpick: if val is not None would be more readable. Commented Mar 29, 2017 at 23:26
  • Also love this answer, but minor correction: 'suppress' is spelled wrong in function def.
    – skelliam
    Commented Sep 9, 2020 at 14:10
0

if you are using flask:

app.jinja_env.finalize = lambda x: x if x is not None else ''

Not the answer you're looking for? Browse other questions tagged or ask your own question.