Can I include a file based on a variable - jinja2

I am trying to include a template file dynamically, but the variable does not appear to expand in the include declaration. How is this best done?
{% for file in files %}
{% include "{{ file }}.txt" %}
{% endfor %}
The error I am getting is:
jinja2.exceptions.TemplateNotFound: {{ file }}.txt

The below works for me.
I would like to clarify having a "." in jinja2 might create an issue so it would be better to pass the entire filename with extension to jinja2.
The usage of double quotes would not render the variable value so it would remain as it is like {{ file }}
The below works:
from jinja2 import Environment, FileSystemLoader
data = '''
{% for file in files.split(",") %}
{% include file %}
{% endfor %}
'''
template = Environment(loader=FileSystemLoader("templates/")).from_string(data)
msg = template.render(files="1.txt")
print(msg)
Output:
1.txt

Related

how can i use jinja template and pillar in saltstack states

there is my sls file:
{% set java_script_path = salt['pillar.get']('script_path', default='/opt/java-app') %}
{% if salt['pillar.get']('script_path') %}
{% set file = {{ java_script_path }}/startup.sh %} ## seem this line have Jinja syntax error
{% if salt['file.file_exists']('{{ file }}') %}
cmd.run:
- name: mv {{ java_script_path }}/startup.sh {{ java_script_path }}/startup.sh.backup-$(date +"%Y-%m-%d-%H-%M-%S")
{% endif %}
{% endif %}
is using salt['pillar.get']('script_path') can not split other string?
example: name: {{ salt['pillar.get']('script_path') }}/startup.sh will raise error like: failed: Jinja syntax error: expected token ':', got '}' how can i fix ?
can you help me to fix my sls file to work?
{% already starts a Jinja context. You do not need to try to start another one with {{.
{% set file = java_script_path ~ "/startup.sh" %}
It was expecting a : because { starts a dict literal.
In simple use case such as shown in your question, you might not even need to set another variable at all. We could directly use {{ java_script_path }}/startup.sh in the if condition. Like below:
{% if salt['file.file_exists']("{{ java_script_path }}/startup.sh") %}
cmd.run:
- name: mv {{ java_script_path }}/startup.sh {{ java_script_path }}/startup.sh.backup-$(date +"%Y-%m-%d-%H-%M-%S")
{% endif %}
You could also reconsider using command to backup the file, and use an appropriate Saltstack module instead.

Using Jinja variable in Yaml file

I have a template folder containing a file.j2 , e.g
{% set summary %}
{% if summary %}
{{ summary }}
% endif %}
{% endset %}
I would like to use this summary variable in my yaml file but I can't seem to be able to find the information on how to reference the j2 file in the yaml file
Can I do this?
template: file.j2
summary: '{{ summary }}'
Any suggestions are greatly appreciated!

Passing list of Relation object to dbt_utils.union_relation macro fails

Related to dbt and jinja2
I am using union_relations from dbt_utils package (0.5.0).
I created my macro which takes list of fully qualified name (like database.schema.identifier) splits it and uses api.Relations.create (link) to create a relation and append each relation to a list.
{{ list_of_relation }} is given to dbt_utils.union_relations(as relations=my_macro([list of fully qualified names])), it's giving me an _is_relation error, I did use log to debug and see if it actually creates a relation and it does. What could be wrong?
It sounds like you have a macro written something like this:
{% macro my_macro(names) %}
{% set list_of_relations = [] %}
{% for name in names %}
{% set relation = something(name) %}
{% do list_of_relations.append(relation) %}
{% endfor %}
{{ list_of_relations }}
{% endmacro %}
Instead of using {{ list_of_relation }}, you’ll want {{ return(list_of_relation) }} or {% do return(list_of_relation) %}. The problem is that {{ ... }} turns things into strings in jinja macros, and macros by default return strings.
The documentation on return is here.

With Jekyll's Liquid syntax, I'd like to use include within a loop, but it errors

The following code error saying "Invalid syntax for include tag. File contains invalid characters or sequences: photo-container.html category='korean' image='custom/gallery/korean/1.jpg' Valid syntax: {% include file.ext param='value' param2='value' %}"
{% for i in (1..1) %}
{% include photo-container.html category='korean' image='custom/gallery/korean/{{i}}.jpg' %}
{% endfor %}
I wonder if it's possible, and if it is, how.
In jekyll inclusions, you can pass parameters as strings or variables like {% include p.html param1="my string" param2=myVar %}. But a variable in a string will not be processed.
The solution is to concatenate your string and assign it to a variable.
{% capture myVar %}My string text {{ anyVar }} text end{% end capture %}
or
{% assign myVar="My string text" | append: anyVar | append: "text end" %}
{% include page.html param1=myVar %}

How to loop through all files in Jekyll's _data folder?

How can I loop through every file in my _data folder in Jekyll?
Currently I have a list of files in a file called sidebarlist.yml like this:
- file1
- file2
- file3
In order to loop through all of these files, I use this code:
{% for sidebar in site.data.sidebarlist %}
{% for entry in site.data.sidebars[sidebar].entries %}
...
{% endfor %}
{% endfor %}
I would like to avoid using sidebarlist.yml and just iterate through all files within _data automatically. Can I do this?
Nesting loops allows you to loop through the contents of _data files.
When I did this I used a subdirectory, since I didn't want to loop through every data file, and I think that applies to many use cases. It also keeps my _data directory a little tidier.
My _data directory looks like this:
_data/
navigation.yml
news.yml
people/
advisors.yml
board.yml
staff.yml
Each of the files within people/ uses a structure like this:
- name: Anne Smith
role: Role A
url: mysite.com
- name: Joe Shmoe
role: Role B
url: mysite.org
And on the page where I'm looping through each of these data files:
{% for people_hash in site.data.people %}
{% assign people = people_hash[1] %}
{% for person in people %}
<li>{{ person.name }}, {{ person.role }}</li>
{% endfor %}
{% endfor %}
This results in:
<li>Anne Smith, Role A</li>
<li>Joe Shmoe, Role B</li>
It's very similar to what you've already done, but eliminates the need for that extra yaml file.
Note the use of people_hash[1] - this is what is targeting the appropriate values within the array.
If instead you do:
{% for people_hash in site.data.people %}
{% assign people = people_hash[1] %}
<pre>{{ people }}</pre>
{% endfor %}
You'll get the array of values that is returned, which should help you debug your template.
I have read your question title, and I will answer your last question:
You can't loop through files you keep in _data folder. According to Jekyll Variable doc and Jekyll Directory structure all the file in _data with supported extension .yml .yaml .csv .jsonby default will be loaded in site.data like #wasthishelpfull's answered and you access it via {{site.data.*filename.data*}} and loop though like this answer
If you wanna loop through files, create a folder (no underscore) serve it as static files, and use jquery.get() for the data in the file.
Or change _data to data in _config.yml by adding data_source: data and access at a url endpoint /data see this post for more
According to the documentation, jekyll will load YAML resources (.yml, .yaml, .json, and .csv files) directly into site.data. If your files use one of these formats, you can do:
{% for data in site.data %}
...
{% endfor %}
I assume you need to access jekyll site.data in a way of looping multi levels object:
{% assign my_data = site.data %}
{% assign my_level = "sidebarlist.sidebars.sidebar" | split: "." %}
{% for level in my_level %}
{% assign my_data = my_data[level[i]] %}
{% for data in my_data %}
{{ data }} : {{ my_data[data] }}
{% endfor %}
{% endfor %}