twig: set variable with function - function

I want to set a variable with the content of a translation function:
{% set somevar = XXXXX %}
Within content, I call the translation like this, but I fail to put the function result into the var:
{% trans into _locale %}somefield{% endtrans %}
I tried many different aproaches, but I always failed, any hint is highly appreciated.

Try with:
{% set somevar %}
{% trans into _locale %}somefield{% endtrans %}
{% endset %}

Found solution:
{% set somevar = 'somefield' %}
{{ somevar|trans(_locale) }}

Related

Store result of a query in a variable ( jinja)

I am trying to put the result of a query in a variable but it doesn't work.
I am not sure what to do so it returns 0 as expected. Any ideas? I am using dbt and jinja.
With the below code the results_list variable is (Decimal('0'),))
MACRO
{% macro source_freshness(model, column_name) %}
{% set freshness_query %}
SELECT COUNT 0 AS count
{% endset %}
{% set results = run_query(freshness_query) %}
{% if execute %}
{% set results_list = results.columns[0].values() %}
{% else %}
{% set results_list = [] %}
{% endif %}
{{ return(results_list) }}
{% endmacro %}
call in a model:
{% set freshness_query_test = source_freshness(ref('model'),'date') %}
{% if count in freshness_query_test == 0 %}
do this
{% else %}
do that
{% endif %}
Thank you!
thanks for your help with this. I have not been able to find a direct answer but what I have done is to add the macro in a separate model, and then use the call statement logic in the shared answer Hi, how do we define select statement as a variable in dbt?

jinja2 using {if} within {for}

I'm trying to make a template which iterates over a list to check if a string exists. if it does then something happens, if the string isn't in the list, something else should happen. The issue is the result is repeated for all the lines in the list, which i do not want.
e.g.
The list is some simple yaml
LIST:
- A
- B
- C
Jinja looks like
{% for line in mylist %}
{% if 'A' in line %}
{{ A }} Was found in the list
{% else %}
{{ A }} Was not found
{% endif %}
{% endfor %}
So when 'A' matches i get this
A Was found in the list
A Was not found
A Was not found
And when 'A' does not match i get this:
A Was not found
A Was not found
A Was not found
Basically i need to stop it iterating over the list and just do one thing if it matches or one thing if it doesn't match
So if 'A' matches i need it to just do
A was found
If 'A' doesn't match i need it to just do A was not found
Use some kind of flag variable:
{% set ns = namespace(found=false) %}
{% for line in mylist %}
{% if 'A' in line %}
{% set ns.found=true %}
{% endif %}
{% endfor %}
{% if ns.foo %}
{{ A }} Was found in the list
{% else %}
{{ A }} Was not found
{% endif %}

How can I concatenate a string using Jinja for loop?

I am trying to iteratively concatenate a string to build url params with a 'for' loop, but I believe I am having scoping issues.
The output should be: url_param = "&query_param=hello&query_param=world"
array_of_objects = [{'id':'hello'},{'id':'world'}]
{% set url_param = "" %}
{% set array_of_ids = array_of_objects|map(attribute='id')|list%} // correctly returns [1,2]
{% for id in array_of_ids %}
{% set param = '&query_param='~id %}
{% set url_param = url_param~param %}
{% endfor %}
//url_param is still an empty string
I also tried namespace(), but to no avail:
{% set ns = namespace() %}
{% set ns.output = '' %}
{% set array_of_ids = array_of_objects|map(attribute='id')|list%} // correctly returns [1,2]
{% for id in array_of_ids %}
{% set param = '&industries='~id%}
{% set ns.output = ns.output~param %}
{% endfor %}
//ns.output returns namespace
That is indeed a scope issue. One "hacky" way of dealing with this is using a list that you append to like so:
{% set array_of_objects = [{'id':'hello'},{'id':'world'}] %}
{% set array_of_ids = array_of_objects|map(attribute='id')|list%}
{{ array_of_ids|pprint }} {# output: ['hello', 'world'] #}
{% set ids = [] %} {# Temporary list #}
{% for id in array_of_ids %}
{% set param = '&query_param='~id %}
{% set url_param = url_param~param %}
{{ ids.append(url_param) }}
{% endfor %}
{{ ids|pprint }} {# output: [u'&query_param=hello', u'&query_param=world'] #}
{{ ids|join|pprint }} {# output: "&query_param=hello&query_param=world" #}
The above gets you what you need, but for this specific example I would take a look at using jinja's join filter. It's more declarative and feels a little less hacky.
{% set array_of_objects = [{'id':'hello'},{'id':'world'}] %}
{# set to a variable #}
{% set query_string = "&query_param=" ~ array_of_objects|join("&query_param=", attribute="id") %}
{{ query_string|pprint }}
{# output: u'&query_param=hello&query_param=world' #}
{# or just use it inline #}
{{ "&query_param=" ~ array_of_objects|join("&query_param=", attribute="id") }}
You should change the initialization of your namespace.
Here is an example from the docs that will help you out:
{% set ns = namespace(found=false) %}
{% for item in items %}
{% if item.check_something() %}
{% set ns.found = true %}
{% endif %}
* {{ item.title }}
{% endfor %}
Found item having something: {{ ns.found }}

Change variable in included jinja2 template

Say I have two templates:
main.j2
{% include "vars.j2" %}
main: {{ var1 }}
vars.j2
{% set var1 = 123 %}
vars: {{ var1 }}
When run, only this line is output:
vars: 123
i.e. var1 is undefined in main.j2, even though it gets set to a value in the included vars.j2 template.
How can I pass variables from included template back to template that includes it? I considered chaining extends, but wondered if there's a more elegant approach.
I recently had a need to do the same thing, and found 2 solutions.
If you have Jinja version 2.10 or later, namespaces can be used:
main_ns.j2:
{% set ns = namespace() %}
{% include "vars_ns.j2" %}
main_ns: {{ ns.var1 }}
vars_ns.j2:
{% set ns.var1 = 123 %}
vars_ns: {{ ns.var1 }}
In Jinja 2.2 or later, it can be accomplished with block scoping of variables. I put the variable settings in the base template so that multiple children can extend it.
vars_block.j2:
{% set var1 = 123 %}
vars_block: {{ var1 }}
{% block content scoped %}{% endblock %}
main_block.j2:
{% extends "vars_block.j2" %}
{% block content %}
main_block: {{ var1 }}
{% endblock %}
You can try using with:
{% with var1=0 %}
{% include "vars.j2" %}
vars: {{ var1 }}
{% endwith %}

Pass variables from child template to parent in Jinja2

I want to have one parent template and many children templates with their own variables that they pass to the parent, like so:
parent.html:
{% block variables %}
{% endblock %}
{% if bool_var %}
{{ option_a }}
{% else %}
{{ option_b }}
{% endif %}
child.html:
{% extends "parent.html" %}
{% block variables %}
{% set bool_var = True %}
{% set option_a = 'Text specific to this child template' %}
{% set option_b = 'More text specific to this child template' %}
{% endblock %}
But the variables end up undefined in the parent.
Ah. Apparently they won't be defined when they are passed through blocks. The solution is to just remove the block tags and set it up like so:
parent.html:
{% if bool_var %}
{{ option_a }}
{% else %}
{{ option_b }}
{% endif %}
child.html:
{% extends "parent.html" %}
{% set bool_var = True %}
{% set option_a = 'Text specific to this child template' %}
{% set option_b = 'More text specific to this child template' %}
If Nathron's solution does not fix your problem, you can use a function in combination with a global python variable to pass a variable value.
Advantage: The variable's value will available in all templates. You can set the variable inside a block.
Disadvantage: More overhead.
This is what I did:
child.j2:
{{ set_my_var('new var value') }}
base.j2
{% set my_var = get_my_var() %}
python code
my_var = ''
def set_my_var(value):
global my_var
my_var = value
return '' # a function returning nothing will print a "none"
def get_my_var():
global my_var
return my_var
# make functions available inside jinja2
config = { 'set_my_var': set_my_var,
'get_my_var': get_my_var,
...
}
template = env.get_template('base.j2')
generated_code = template.render(config)
In some cases, you can avoid this 'parameter-passing' by creating another variant of the parent that adds/removes some block and extends it instead.
{% extends [condition]|yesno:'parent_1.html,parent_2.html' %}