For loop in jinja using exported variable - jinja2

I am trying to generate some code in a for loop and the limit is set dynamically from an exported variable. This is what I was trying
In test.mk
export num_iterations = 3
In test.j2
{%- for i in range(0, {{ num_iterations | int }}) %}
Do something with {{i}}
{%- endfor %}
Error I get
jinja2.exceptions.TemplateSyntaxError: expected token ':', got '}'
If I use range(0, 3), the code generation works fine.
Thanks

Try removing the inner {{ }} so your for looks like this:
{%- for i in range(0, num_iterations | int ) %}

Related

How can I use {{this}} as a parameter in a dbt jinja macro?

How can I pass the name of the current model using {{this}} as a parameter for a macro in a config function?
I have tried a couple of options and none of them works.
model/Table1.sql
{{ config(post_hook= calculate_test("{{this}}") ) }}
macro/calculate_test.sql
{% macro calculate_test(tableN) %}
{%- set tableName = tableN -%}
{% set sql %}
SELECT
COUNT(*) as cnt
FROM {{ tableName }}
{% endset %}
{% set results = run_query(sql) %}
{% endmacro %}
The error is:
You’re almost there! Only thing is that you’ve got extra curly brackets and misplaced quotes. The entire config block is Jinja so you don’t need the curly brackets around ‘this’.
{{ config(post_hook= “calculate_test(this)” ) }}

Comparing timestamps gives type error in jinja2 template

I'm trying to compare two timestamps but getting a type error:
"TypeError: '<' not supported between instances of 'float' and 'str'
The template code is using 'as_timestamp' and the documentation recommended using float() when comparing.
I'm trying to get the name and date of the sensor that has a date value that is closest to now() (in Home Assistant).
So I'm trying to do the following:
{%- set list = ['sensor.1','sensor.2','sensor.3','sensor.4'] -%}
{%- set data = namespace(min_date=float(as_timestamp(now() + timedelta(days = 360))), min_name = '') -%}
{%- for i in list %}
{%- set value = states(i) %}
{%- if float(as_timestamp(value)) < float(data.min_date) %}
{%- set data.min_date = value -%}
{%- set data.min_name = state_attr(i, 'friendly_name') -%}
{% endif %}
{%- endfor %}
{{ data.min_name + ' (' + data.min_date | timestamp_custom('%Y-%m-%dT%H:%M:%S%z') + ')' }}
Any ideas why data.min_date is a str in the comparison, despite the value being defined with both float() and as_timestamp() ?
had to remove the 'as_timestamp' from the initial value assignment and add it to the if statement. that solved it.

How to increment two variables on a for-loop in jinja template?

I am developing a web using flask. I have two class objects from models.py. I need to loop over both of them at the same time in my HTML file using Jinja2.
For example:
I want to have the following code in jinja2 format:
for i,j in zip(items, team):
a= i+j
Want to convert it to jinja2 format:
{% for i,j in zip(items, teams) %}
{% a=i+j %}
{% endfor%}
What is the problem with this jinja2 code?
Jinja doesn't actually have a zip global function. So you need to make it available by doing:
app.jinja_env.globals.update(zip=zip)
Additionally, assignments require using the set keyword, e.g. {% set a = i + j %}
{% for i, j in items %}
{% set a = i + j %}
{% endfor %}
See also: "zip(list1, list2) in Jinja2?"
Thank you , it was very helpful. I just did this and worked:
in init.py file I add this:
app.jinja_env.filters['zip'] = zip
in the index.html:
{% for i, j in items | zip(teams) %}
{% set a = i + j %}
{% endfor %}

Jinja2: use template to build a string variable

Jinja2 supports very useful filters to modify a string, eg.
{{ my_string|capitalize }}
What about you want to build the input string? When the string is simple you can always use
{% set my_string = string_1 + string_2 %}
{{ my_string|capitalize }}
But it would be wonderful to actually build this string using templates, just like
{% set my_string = "{{ 'a' }}b{{ 'c' }}" %}
{{ my_string|capitalize }}
that would output Abc..
Did I miss something?
Answer exists in Jinja 2.8, as documented here
The answer is
{% set my_string %}
{{ 'a'}}b{{ 'c' }}
{% endset %}

how to access pillar data with variables?

I have a pillar data set like this;
vlan_tag_id:
nginx: 1
apache: 2
mp: 3
redis: 4
in the formula sls file I do this;
{% set tag = pillar.get('vlan_tag_id', 'u') %}
so now I have a variable tag which is a dictionary {'apache': 2, 'nginx': 1, 'redis': 4, 'mp': 3}
At run time I pass a pillar data app whose value will be either
1. apache
2. nginx
3. redis
4. mp
so if at run time I pass apache I want to something which will get me the value 2
I cant do {{ salt['pillar.get']('vlan_tag_id:app', '')}} because app itself is a variable.
I tried doing {{ salt'pillar.get'}}, but it throws error.
how can I do this ?
Since tag is just another dictionary, you can do a get on that as well:
{%- set tag = pillar.get('vlan_tag_id', 'u') %}
{%- set app = pillar.get('app') %}
{{ tag.get(app) }} # Note lack of quotes
If you want to use the colon syntax, you can append the contents of app to the key string:
{%- set app = pillar.get('app') %}
{{ salt['pillar.get']('vlan_tab_id:' + app) }}
I find it simpler to follow if I alias pillar.get and break it up a bit:
{%- set pget = salt['pillar.get'] %}
{%- set app = pget('app') %}
{%- set tag = pget('vlan_tag_id') %}
{{ tag.get(app) }}