What is the difference between Jinja's defined vs if variable_name? - jinja2

What is the difference between these two items? When do you use one vs the other?
{% if x is defined %}
words
{% endif %}
and
{% if x %}
words
{% endif %}

The second one enforces you to provide x as a variable. If you won't set x at all, then it'll be an error. The first item will be skipped if x wasn't provided

Related

Jinja non rendering blocks adds whitespaces to next rendering block

I have the following import on a jinja template that is rendered by ansible:
labels:
{% set name = 'jellyfin' %}
{% set port = '8096' %}
{% filter indent(width=8, first=True) %}
{% include './labels.yml.jinja' %}
{% endfilter %}
As you can see, there are some non rendering blocks to set some local variables and stuff. When the template is rendered by ansible, the first row of the template is shifted by the same amount of spaces that the non rendering blocks sum + 2 (32 in this case = 5 blocks with 6 spaces + 2).
For example:
labels:
# this are the labels, fools
- "traefik.enable=true"
- "traefik.backend=jellyfin"
I can remove the indentation of ALL the {% %} blocks, and then it will work properly, but looks ugly and off place.
Even if I add a minus sign to remove whitespaces to the non rendering blocks like this:
{% set name = 'jellyfin' -%}
{% set port = '8096' -%}
{% filter indent(width=8, first=True) -%}
{% include './labels.yml.jinja' -%}
{% endfilter -%}
The first line is still shifted (albeit much less)
How can I fix this?
I just had to add #jinja2: lstrip_blocks: "True" to the very top of the importing template, and that did the trick.
I gathered that information from this article, explaining my exact problem and showing a solution: https://radeksprta.eu/posts/control-whitespace-in-ansible-templates/
But I have to say that the default behaviour is very confusing.

Searching for page in site.pages by path without iteration

I have a path to some page from root in Jekyll as a variable path. I want to get some variables from FrontMatter of that page. How could I find this page in site.pages without iterating over all pages?
I mean something like
{% assign aim = site.pages[path] %}
instead of
{% for p in site.pages %}
{% if p.path == path %}
{% assign aim = p %}
{% endif %}
{% endfor %}
Will this solution be faster for a site with a thousand of pages?
You can use the where liquid filter for this:
{% assign aim = site.pages | where:"path",path %}
Thanks #β.εηοιτ.βε for the hint!
That was what I expected, but when I used this template, I've faced the problem: the output of {{aim.title}} was empty.
The where filter produces list even it consists of just one element! But each filepath in a file system points exactly at one file, so I expected that aim will be the page, not a list. To fix this, I've added first filter:
{% assign aim = site.pages | where:"path",path | first %}
And now aim is the page variable I am searching for.
About speed. This solution builds a site 2X faster on my hardware.

How do i compare a String out of a list in Jinja2 to another string?

I'm using a for loop and inside that forloop i generate tables out of DataBase data.
The thing is that i need to show multiple tables, but the if statement in Jinja2 doesn't seem to work for some reason. I need to check if the string on index 2 of my_list[2] is equal to the 'None'.
{% if '{{my_list[2]}}' == 'None' %}
There is no connection.
{% else %}
There is a GOOD connection.
{% endif %}
Why isn't this working?
{% if not customer_list[2] %}
This does exactly wat i needed.

Jinja join list of strings if substring match

Is it possible to do something like this in jinja2:
my_list = ['foo1', 'bar1', 'foo2', 'bar2'] # could be any number of foo's and bar's
[i for i in my_list if 'foo' in i]
I was looking at map and join, something like:
{% my_list|map('???')|join(' ') %}
But I can't find a filter that would like me do any sort of wildcard searches. The two closest ones look like 'sameas' and 'equalto' but those don't quiet work.
If you're using a recent version of Jinja2 (2.7 or later), there's a new filter called 'select', which seems to do what you want. jinja.pocoo.org/docs/dev/templates/#select You will probably have to write your own test for this, and pass it into the jinja2 object when you instantiate it.
{{ foobars|select("test") }}
If you're on an even more up to date version (2.8 or later), you can also use block assignments http://jinja.pocoo.org/docs/dev/templates/#block-assignments
{% set my_foo_bars %}
{%- for item in my_list %}
{%- if item %}
{{item}}
{% endif -%}
{% endfor -%}
{% endset %}
If you're stuck on an older version (like the jinja2 from google app engine), you would probably be best doing the processing before passing it into the template, if possible.

Template for loop if the current iteration is different from the previous iteration

I want to have
{% for user_id, x, y in information %}
{% if it is the first time that user_id is different from the previous iteration %}
do something
{% elseif user_id is different from the user_id in the previous iteration %}
do something
{% endif %}
Can anyone help. Thanks!!!
You are looking for {% ifchanged %}. Have a look here: https://docs.djangoproject.com/en/dev/ref/templates/builtins/#ifchanged