Search code examples
python-3.xjinja2

Using "if any():" in Jinja2?


In Jinja2 I'm looking for a way to check if at least one of a list of variables has a value. Basically in python I would do:

if any([item['genre'], item['type'], item['color']]):

However, in Jinja the following isn't valid:

{% if any([item['genre'], item['type'], item['color']]) %}
# some part of the Jinja template
{% endif %}

Is there a way to have the same "any()" check in Jinja2?

For background: the full piece of code that I currently try to add (but isn't valid):

{% if any([item['genre'], item['type'], item['color']]) %}
<ItemProperties>
    <ItemProperty key="genre">{{ item['genre'] }}</ItemProperty>
    <ItemProperty key="type">{{ item['type'] }}</ItemProperty>
    <ItemProperty key="color">{{ item['color'] }}</ItemProperty>
</ItemProperties>
{% endif %}

Solution

  • There is no direct equivalent of the any() function in Jinja2 templates.

    For 3 hard-coded elements, I'd just use boolean logic or:

    {% if item['genre'] or item['type'] or item['color'] %}
    

    Otherwise, you can use the select() filter without an argument (followed by first() to force iteration). Because select() is itself a generator, using first() on select() makes this short-circuit the way any() would:

    {% if (item['genre'], item['type'], item['color'])|select|first %}
    

    Without an argument, select() returns any objects from the input sequence that are true, and first() ensures it iterates no more than needed to find one such element.

    The last option is to register a custom filter to just add any() to Jinja yourself; I'd also add all() in that case. You can register both functions directly, since neither takes options:

    environment.filters['any'] = any
    environment.filters['all'] = all
    

    at which point you can then use

    {% if (item['genre'], item['type'], item['color'])|any %}