Jinja Template - list - jinja2

Below are my input.yaml and my template.jinja:
input.yaml:
animals:
my_pets:
- species:
name: "cat"
age: "28"
- species:
name: "dog"
age: "10"
template.jinja
{%- for pet in animals.my_pets %}
Type: {{ pet.species.name }}
Name: {{ pet.species.age }}
{%- endfor %}
The result should be like the input.yaml
animals:
my_pets:
- species:
name: "cat"
age: "28"
- species:
name: "dog"
age: "10"
For sure something is not right on my template as it doesn't render the expected structure but I don't find what.
I've made some modification and somehow it work, but not as intended.
new_input.yaml:
my_pets:
- species:
- name: "cat"
- age: "28"
- species:
- name: "dog"
- age: "10"
new_template.jinja:
my_pets:
{%- for intf in my_pets %}
{%- for i in intf.species %}
{%- for key,value in i.items() %}
- species:
- {{ key }}: "{{ value }}"
{%- endfor %}
{%- endfor %}
{%- endfor %}
The new_output is like this:
my_pets:
- species:
- name: "cat"
- species:
- age: "28"
- species:
- name: "dog"
- species:
- age: "10"
But it should be like this:
animals:
my_pets:
- species:
name: "cat"
age: "28"
- species:
name: "dog"
age: "10"

In a loop like:
{%- for key,value in dict.items() %}
{%- endfor %}
What you are doing is to loop on the different attributes of a dictionary — in your case name and age, so:
you should not start your line with a - or you will create a list:
{%- for key,value in dict.items() %}
{{ key }}: "{{ value }}"
{%- endfor %}
the loop will iterate on each attribute of the dictionary, so, your parent attribute, species, should be on top of the loop, not inside it:
- species:
{%- for key,value in dict.items() %}
{{ key }}: "{{ value }}"
{%- endfor %}
Given your input, this loop will recreate the same list of dictionaries as inputted:
my_pets:
{%- for pet in animals.my_pets %}
- species:
{%- for key, value in pet.species.items() %}
{{ key }}: "{{ value }}"
{%- endfor %}
{%- endfor %}

Related

Not able to access dictionary value in Macro DBT

I am accessing a dictionary variable which is defined in the marco
{% macro normalize_state(column_name) -%}
{% set states_dict = {
"Alabama" : "AL",
"Alaska" : "AK",
...
....
} -%}
CASE WHEN {{column_name}} IS NOT NULL THEN '{{ states_dict.get(column_name) }}'
ELSE NULL END
{%- endmacro %}
But '{{ states_dict.get(column_name) }}' produced the output None
Macros are compiled (templated) before the query is run. That means that the data in your database doesn't run through the jinja templater.
{{ states_dict.get(column_name) }} looks up the name of the column in your dictionary, not the data it contains.
What you need to do is use your dictionary to write a case statement that performs the get operation. That looks like this:
{% macro normalize_state(column_name) -%}
{% set states_dict = {
"Alabama" : "AL",
"Alaska" : "AK",
...
} -%}
case
{% for k, v in states_dict.items() %}
when {{ column_name }} = '{{ k }}'
then '{{ v }}'
{% endfor %}
end
{%- endmacro %}
Then you need to pass in column_name as a string (quoted) when you call the macro:
select {{ normalize_state("my_column") }}

Twig Template: Looping a two dimensional Array

I have an PHP Array like this:
$fruits = array(
array("Apple", 1.25),
array("Banana", 0.86),
);
What I wanted:
Then I simply wanted the HTML output like this:
Fruit: Apple
Price: 1.25
Fruit: Banana
Price: 0.86
What I tried:
I have already tried looping like:
{% for fruits in data["fruits"] %}
{% for fruit in fruits %}
Fruit: {{ fruit[0] }}
Price: {{ fruit[1] }}
{% endfor %}
{% endfor %}
.. which didn't work.
Only this worked:
{% for fruits in data["fruits"] %}
{% for fruit in fruits %}
{{ fruit }}
{% endfor %}
{% endfor %}
.. but it gave the output like this:
Apple 1.25 Banana 0.86
How do I get the result like I mentioned in "What I wanted:" section above, please?
You just could do this:
{% for fruit in fruits %}
Fruit: {{ fruit[0] }}<br />
Price: {{ fruit[1] }}<br />
{% endfor %}

How can I access JSON identifiers from Twig?

These are my JSON data:
[
{
"name":"unit 1",
"lessons":{
"1":{
"name":"lesson 1",
"content":"......."
},
"2":{
"name" "lesson 2",
"content":"......."
}
}
]
I can access these data using the following Twig code:
{% for unit in units %}
{{ unit.name }}
{% for lesson in unit.lessons %}
{{ lesson.name }}
{% endfor %}
{% endfor %}
But I want to access the lesson number, to make a hyperlink to the content. How can I do that?
You can Iterating over Keys and values as example:
{% for key, lesson in unit.lessons %}
{{ key}}
{{ lesson.name }}
{% endfor %}
Hope this help

Jekyll iterate over a triple dimension array

Using Jekyll 3.3 I create an array into the _config.yml file :
profiles:
- user1:
- username: "test"
- link: "http://test.test"
I want to get the value username and link for each user. So I use a double loop :
{% for profile in site.profiles %}
{% for user in profile %}
{{ user.username }}
{% endfor %}
{% endfor %}
But that doesn't print anything, Did I miss something ?
With datas arranged like this :
profiles:
- username: "test"
link: "http://test.test"
- username: "test2"
link: "http://test.test2"
You can do :
{% for user in site.profiles %}
{{ user.username }}
{% endfor %}

Nesting variables in Jekyll/Liquid

Assumption - From what I understand, Liquid works in a way that the variable page.my_key can be compared to a PHP array with name page and key my_key: $page['my_key']. Following this same logic we could compare {{ page.my_key }} with echo $page['my_key'].
And we could compare this front matter:
----
my_key: my_value
----
to this PHP code:
$page['my_key'] = "my_value";
Question - I would like to do something like this:
$page['my_key'] = "my_value";
$page['my_key2'] = "my_value2";
$key = "my_key";
echo $page[$key];
All I can think of is:
----
my_key: my_value
my_key2: my_value2
----
{% assign key = 'my_key' %}
{{ page.{{ key }} }}
However, that does not work... Is something like this possible, though?
Beware : array and hash are two different animals.
Just create a array-hash.md (note I wrote it in markdown for brevity) page in your jekyll. Paste this code. And you will understand how they are different and how to access their items.
---
layout: default
title: array-hash
myArray:
- item 1
- item 2
- one more
# or
myArray2: [ item 1, item 2, one more item ]
myHash:
item1: toto
"item 2": titi
item 3: yoyo
---
{% comment %} +++ Shortcuts
a = page.myArray
h = page.MyHash
h2 = page.myArray2
{% endcomment %}
{% assign a = page.myArray %}
{% assign a2 = page.myArray2 %}
{% assign h = page.myHash %}
## Arrays
page.myArray : {{ a }}
page.myArray with inspect : {{ a | inspect }}
page.myArray with join : {{ a | join:", " }}
page.myArray2 : {{ a2 | inspect }}
### Looping the array
<ul>
{% for item in a %}
<li>{{ item | inspect }}</li>
{% endfor %}
</ul>
### Targeting a specific item in the array
{% comment %} arrays start at zero {% endcomment %}
second element in the array = {{ a[1] }}
Note that {% raw %}{{ a["1"] }}{% endraw %} will not work. You need to pass
an integer and not a string.
Test (not working) : { a["1"] }
## Hashes
page.myHash : {{ h }}
#### looping the hash
{% for item in h %}
{{ item | inspect }}
{% endfor %}
You note that in the loop we get arrays that returns **key as item[0]**
and **value as item[1]**
The loop can then look like :
<ul>
{% for item in h %}
<li>{{ item[0] }} : {{ item[1] }}</li>
{% endfor %}
</ul>
### Targeting a specific item in the hash
**Item1** due to the absence of space in the key name, can both me accessed
by dot notation (h.item1) or bracket notation (h["item1"]).
hash.item1 : {{ h.item1 }}
hash["item1"] : {{ h.["item1"] }}
Item 2 and 3, containing a space in their key string can only be accessed with
bracket notation :
hash.item 2 (not working) : {{ h.item 2 }}
hash["item 2"] : {{ h.["item 2"] }}
hash.item 3 (not working) : {{ h.item 3 }}
hash["item 3"] : {{ h.["item 3"] }}
I think I found the solution:
----
my_key: my_value
my_key2: my_value2
----
{% assign key = 'my_key' %}
{{ page[key] }}
Found it here.