71

I need to check if the variable texts is defined or not in index.html.

If the variable is defined and not empty then I should render the loop. Otherwise, I want to show the error message {{error}}.

Basically this in PHP

if (isset($texts) && !empty($texts)) {
    for () { ... }
}
else {
    print $error;
}

index.html

{% for text in texts %} 
    <div>{{error}}</div>
    <div class="post">
        <div class="post-title">{{text.subject}}</div>
        <pre class="post-content">{{text.content}}</pre>
    </div>
{% endfor %}

How do I say this in jinja2?

phs
  • 10,687
  • 4
  • 58
  • 84
daniel__
  • 11,633
  • 15
  • 64
  • 91

10 Answers10

71

I think your best bet is a combination of defined() check along with looking at the length of the array via length() function:

{% if texts is defined and texts|length > 0 %}
    ...
{% endif %}
Community
  • 1
  • 1
andyfeller
  • 905
  • 1
  • 7
  • 12
56

To test for presence ("defined-ness"?), use is defined.

To test that a present list is not empty, use the list itself as the condition.

While it doesn't seem to apply to your example, this form of the emptiness check is useful if you need something other than a loop.

An artificial example might be

{% if (texts is defined) and texts %}
    The first text is {{ texts[0] }}
{% else %}
    Error!
{% endif %}
phs
  • 10,687
  • 4
  • 58
  • 84
31

Take a look at the documentation of Jinja2 defined(): http://jinja.pocoo.org/docs/templates/#defined

{% if variable is defined %}
    value of variable: {{ variable }}
{% else %}
    variable is not defined
{% endif %}

Is it clear enough? In your case it could look like this:

{% if texts is defined %}
    {% for text in texts %} 
        <div>{{ error }}</div>
        <div class="post">
            <div class="post-title">{{ text.subject }}</div>
            <pre class="post-content">{{ text.content }}</pre>
        </div>
    {% endfor %}
{% else %}
    Error!
{% endif %}
Tadeck
  • 132,510
  • 28
  • 152
  • 198
13

As mentioned in the documentation, you could also write:

{% for text in texts %}
    <div class="post">
        <div class="post-title">{{text.subject}}</div>
        <pre class="post-content">{{text.content}}</pre>
    </div>
{% else %}
    <div>{{ error }}</div>
{% endfor %}

It handles both the case where texts is undefined, and the case where texts is empty.

Mathieu Bridon
  • 640
  • 7
  • 11
8

This is a neat and simple solution that worked well for me!

{% if texts is defined and texts[0] is defined %}
    ...
{% endif %}
sonictolfa
  • 81
  • 1
  • 2
3

It's possible that texts could be defined but contain a single list element which is an empty string; For example:

texts = ['']

In this case, testing if texts is defined will produce a true result so you should test the first element instead:

{% if texts[0] != '' %}
    ..code here..
{% endif %}

You might also want to combine that with the |length filter to make sure it only has one element.

foobrew
  • 1,766
  • 1
  • 11
  • 3
1

This worked for me when working with the UPS API where if there is only one object in a parent object the child is just an object, but when there is more than one child it's a array of objects.

{% if texts[0] %}
    ..code here..
{% endif %}
Erich Wehrmann
  • 464
  • 2
  • 11
0

This is what worked for my use case in my Django app:

I needed to pass a queryset as context to an html template and display the block only if the queryset had values

Queryset:

events = Event.objects.filter(schedule_end__gte=date.today()).order_by('-created_at')

Passed context dictionary as follows:

{ "events" : events }

HTML template

{% if events %}
  <h3>Upcoming Events</h3>
  <ul>
    {% for event in events %}
    <li><h4>{{ event.title }}</h4></li>
    {% endfor %}
  </ul>
{% endif %}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Amal Vijayan
  • 649
  • 2
  • 6
  • 26
0

This works for me ( But I make sure to return an empty array [] and not None if its empty )

{% if array  %}

   <table class="table">
       ...
   </table>

{% endif %}
Am Ben
  • 89
  • 5
0

We can check if array is not empty by writing below jinja code. where the content2 is an array defined under py file. @app.route("/<name>") def home(name): return render_template("index.html", content=name, content2=[])

{% if content2 %}
<div>
    <h2>Array elements are available</h2>
    {% for con2 in content2 %}
        <p> {{con2}} </p>
    {% endfor %}
</div>
{% endif %}

Thanks

Avinash
  • 159
  • 2
  • 9