Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Does Jinja support variable assignment as a result of a loop?

I’ve been using Jinja and DBT for a month now, and despite reading a lot about it, I didn’t quite figure out how to create a list from another, using a simple for loop like I would in Python.
Just a toy example:

{%- set not_wanted_columns = ['apple', 'banana'] -%} 
{%- set all_columns = ['kiwi', 'peach', 'apple', 'banana', 'apricot', 'pineapple'] -%}

What I want is a list as so:

{% set filtered_columns = ['kiwi', 'peach', 'apricot', 'pineapple'] %}

Naturally, I don’t want to manually write this result because the full list might be dynamic or too long. I’m not even sure if Jinja does actually support this, although I do think this is a common problem.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

As you have probably read from the documentation:

Please note that assignments in loops will be cleared at the end of the iteration and cannot outlive the loop scope. Older versions of Jinja had a bug where in some circumstances it appeared that assignments would work. This is not supported.

Source: https://jinja.palletsprojects.com/en/3.1.x/templates/#for

And I guess when you are speaking about

using a simple for loop like I would in Python

What you mean here is using a list comprehension.

So, as showed in the documentation, Jinja is using filter to achieve this:

Example usage:

{{ numbers|select("odd") }} 
{{ numbers|select("divisibleby", 3) }} 

Similar to a generator comprehension such as:

(n for n in numbers if test_odd(n))
(n for n in numbers if test_divisibleby(n, 3)) 

Source: https://jinja.palletsprojects.com/en/3.1.x/templates/#jinja-filters.select

There are actual four of those filter acting as generator comprehension:


So, in your case, a reject filter would totally do the trick:

{%- set filtered_columns = all_columns
     | reject('in', not_wanted_columns) 
     | list 
-%}

But, if you really want, you could also achieve it in a for:

{%- for column in all_columns if column not in not_wanted_columns -%}
  {% do filtered_columns.append(column) %}
{%- endfor -%}

The do statement being a way to use list.append() without oddities being printed out: https://jinja.palletsprojects.com/en/3.1.x/templates/#expression-statement.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading