275

How to make a variable in Jijna2 default to "" if object is None instead of doing something like this?

{% if p %}   
    {{ p.User['first_name']}}
{% else %}
    NONE
{%endif %}

So if object p isNone. I want to default the values of p (first_name and last_name) to "". Basically:

nvl(p.User[first_name'], "")

Error receiving:

Error: jinja2.exceptions.UndefinedError
UndefinedError: 'None' has no attribute 'User'

3
  • 1
    Make the function that returned the value of p never return None. Instead of None the function should return a proxy object that has the same structure as a real object but it is loaded with the default values that you want. Commented Oct 27, 2013 at 4:23
  • 1
    I use this, and my problem was solved: {% if p != None %} {{ p.User['first_name'] }} {% endif %} Commented Dec 23, 2018 at 14:53
  • See also: In Jinja2, how do you test if a variable is undefined? Commented Jun 22, 2019 at 5:02

14 Answers 14

451

Use the none test (not to be confused with Python's None object!):

{% if p is not none %}   
    {{ p.User['first_name'] }}
{% else %}
    NONE
{% endif %}

or:

{{ p.User['first_name'] if p is not none else 'NONE' }}

or if you need an empty string:

{{ p.User['first_name'] if p is not none }}
Sign up to request clarification or add additional context in comments.

3 Comments

Notice the lowercase none in the answer. My problem was solved after I corrected None's case.
This is the best answer because so many others do not differentiate between False and None. This example uses the term "first_name" which we can assume will not expect a value of False, but there are many cases where a system needs to treat False and None differently. Things like {{p.User['first_name'] or 'default'}} will not catch that case and will convert False to the default case incorrectly. Other interesting cases are 0, [], and "".
it's kind of curious why != None works but is not None don't and for this, you need to use in lowercase: is not none
185
{{p.User['first_name'] or 'My default string'}}

1 Comment

This might be shooting in the foot when using with boolean values? I.e. if p.User['first_name'] is false will the result be as expected: false?
115

According to docs you can just do:

{{ p|d('', true) }}

Cause None casts to False in a boolean context.

2 Comments

This works for a simple variable, but not for this question where you're looking to grab a field out of a more complex one. I would downvote this, since it's not a good answer to the original question... and yet at the same time, knowing about default is exactly what I needed for my particular case, so... simply not voting. (An edit to this answer might well earn it an upvote, except that I think it's likely hard to apply default to this situation)
I think the mention regarding default only works in simple data types is outdated. I have this working with an empty list, default([])
62

As addition to other answers, one can write something else if variable is None like this:

{{ variable or '' }}

4 Comments

I am amazed this simplicity! Python's x or y is if x is false, then y, else x. See: 5.2. Boolean Operations — and, or, not
This worked for me where others failed.
Jinja2 3.1.4 failed to resolve {{ var | default('whatever') }}, rendering it to pythonic "None". But your method was bliss!
@kenjiuno I think you'll find that the exact same syntax works in python...
31

Following this doc you can do this that way:

{{ p.User['first_name']|default('NONE') }}

3 Comments

I don't think so - the "default" template filter returns the default value if the value is undefined/missing.
Worked for me when using ansible. This made it more clear: stackoverflow.com/q/28885184/1005215
If p is defined. But if P isn't defined it doesn't work
10

To avoid throw a exception while "p" or "p.User" is None, you can use:

{{ (p and p.User and p.User['first_name']) or "default_value" }}

2 Comments

This is the only one that worked for me given my variable was buried deep in a dict.
This helps clean up some others with lots of logic.
8

With ChainableUndefined, you can do that.

>>> import jinja2
>>> env = jinja2.Environment(undefined=jinja2.ChainableUndefined)
>>> env.from_string("{{ foo.bar['baz'] | default('val') }}").render()
'val'

source

Comments

2

if you want to set your own default value instead of None than simply do this

{{your_var|default:'default name'}}

Comments

1

As another solution (kind of similar to some previous ones):

{{ ( p is defined and p.User is defined and p.User['first_name'] ) |default("NONE", True) }}

Note the last variable (p.User['first_name']) does not have the if defined test after it.

Comments

1

for 0 value i need to use if val is None else structure, so added filter ifnone:

def ifnone(val, default):
    if val is None:
        return default
    return val

...
env.filters["ifnone"] = ifnone

Useage in template: {{val|ifnone('--')}}

Comments

0

I usually define an nvl function, and put it in globals and filters.

def nvl(*args):
    for item in args:
        if item is not None:
            return item
    return None

app.jinja_env.globals['nvl'] = nvl
app.jinja_env.filters['nvl'] = nvl

Usage in a template:

<span>Welcome {{ nvl(person.nick, person.name, 'Anonymous') }}<span>

// or 

<span>Welcome {{ person.nick | nvl(person.name, 'Anonymous') }}<span>

Comments

0

I solved this by defining a custom filter (in my case I needed in the cases None, False or empty strings):

def __default_if_empty(value, default) :
    """Returns a default value if the given value evaluates to False."""
    return value if value else default

env = Environment(
    # Your config...
)
env.filters["default_if_empty"] = __default_if_empty

Then use that filter in the template:

{{ your_var | default_if_empty('') }}

Comments

-2

As of Ansible 2.8, you can just use:

{{ p.User['first_name'] }}

See https://docs.ansible.com/ansible/latest/porting_guides/porting_guide_2.8.html#jinja-undefined-values

Comments

-2

You can simply add "default none" to your variable as the form below mentioned:

{{ your_var | default('NONE', boolean=true) }}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.