daniel__
daniel__

Reputation: 11845

Check if an array is not empty in Jinja2

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?

Upvotes: 77

Views: 139652

Answers (10)

Avinash
Avinash

Reputation: 326

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

Upvotes: 0

Erich Wehrmann
Erich Wehrmann

Reputation: 522

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 %}

Upvotes: 1

Am Ben
Am Ben

Reputation: 119

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 %}

Upvotes: 1

Amal Vijayan
Amal Vijayan

Reputation: 739

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 %}

Upvotes: 0

sonictolfa
sonictolfa

Reputation: 81

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

{% if texts is defined and texts[0] is defined %}
    ...
{% endif %}

Upvotes: 8

phs
phs

Reputation: 11061

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 %}

Upvotes: 61

Mathieu Bridon
Mathieu Bridon

Reputation: 660

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.

Upvotes: 14

andyfeller
andyfeller

Reputation: 983

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 %}

Upvotes: 78

foobrew
foobrew

Reputation: 1765

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.

Upvotes: 3

Tadeck
Tadeck

Reputation: 137420

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 %}

Upvotes: 30

Related Questions