Generate YAML using Jinja2 Templates in Python
In this tutorial, you’ll learn how to use Jinja2 templates to generate YAML files dynamically in Python.
Jinja2 is a templating engine that allows you to create reusable templates for various file formats, including YAML.
Create Jinja2 Templates for YAML
To use Jinja2 for YAML generation, you must install the Jinja2 library and create a template with placeholders.
You can install Jinja2 using pip:
!pip install Jinja2
Now, let’s create a simple YAML template using Jinja2 placeholders:
from jinja2 import Template yaml_template = """ name: {{ name }} age: {{ age }} city: {{ city }} """ template = Template(yaml_template) rendered_yaml = template.render(name="Amr", age=30, city="Cairo") print(rendered_yaml)
Output:
name: Amr age: 30 city: Cairo
The template uses double curly braces {{ }}
to define placeholders for variables.
When rendering the template, you pass the values for these variables, and Jinja2 replaces the placeholders with the provided data.
Variables and Expressions in Jinja2
You can define and use variables directly within Jinja2 templates:
from jinja2 import Template yaml_template = """ {% set greeting = "Marhaban" %} message: {{ greeting }}, {{ name }}! details: age: {{ age }} city: {{ city }} """ template = Template(yaml_template) rendered_yaml = template.render(name="Fatma", age=25, city="Alexandria") print(rendered_yaml)
Output:
message: Marhaban, Fatma! details: age: 25 city: Alexandria
The {% set %}
directive allows you to define variables within the template itself.
These variables can then be used alongside the context variables passed during rendering.
Expressions and math operations
Jinja2 supports various expressions and math operations within templates:
from jinja2 import Template yaml_template = """ product: name: {{ product_name }} price: {{ price }} discounted_price: {{ price * 0.9 }} tax: {{ price * 0.1 }} total: {{ price * 1.1 }} """ template = Template(yaml_template) rendered_yaml = template.render(product_name="Egyptian Cotton Sheets", price=100) print(rendered_yaml)
Output:
product: name: Egyptian Cotton Sheets price: 100 discounted_price: 90.0 tax: 10.0 total: 110.0
Using default values and variable evaluation
Jinja2 provides ways to set default values and evaluate variables:
from jinja2 import Template yaml_template = """ user: name: {{ name | default("Guest") }} premium: {{ premium | default(false) }} visits: {{ visits | default(0) }} status: {{ "Active" if visits > 5 else "Inactive" }} """ template = Template(yaml_template) rendered_yaml = template.render(name="Hossam", visits=7) print(rendered_yaml)
Output:
user: name: Hossam premium: false visits: 7 status: Active
The default
filter sets a fallback value if the variable is not provided.
The if
expression allows for conditional evaluation within the template.
Control Structures in Templates
Jinja2 supports conditional statements for dynamic content generation.
The if
, elif
, and else
statements allow you to create conditional blocks in your templates.
from jinja2 import Template yaml_template = """ user: name: {{ name }} age: {{ age }} status: {% if age < 18 %} minor {% elif age < 65 %} adult {% else %} senior {% endif %} """ template = Template(yaml_template) rendered_yaml = template.render(name="Nour", age=30) print(rendered_yaml)
Output:
user: name: Nour age: 30 status: adult
For loops
You can use for
loops to iterate over lists and dictionaries:
from jinja2 import Template yaml_template = """ team: name: {{ team_name }} members: {% for member in members %} - name: {{ member.name }} role: {{ member.role }} {% endfor %} """ team_data = { "team_name": "Pyramid Builders", "members": [ {"name": "Amira", "role": "Architect"}, {"name": "Karim", "role": "Engineer"}, {"name": "Laila", "role": "Project Manager"} ] } template = Template(yaml_template) rendered_yaml = template.render(**team_data) print(rendered_yaml)
Output:
team: name: Pyramid Builders members: - name: Amira role: Architect - name: Karim role: Engineer - name: Laila role: Project Manager
The for
loop iterates over the members
list, creating a YAML list item for each member with their name and role.
Nested control structures
You can combine loops and conditionals for more complex structures:
from jinja2 import Template yaml_template = """departments: {% for dept, employees in departments.items() %} {{ dept }}: {% for employee in employees %} - name: {{ employee.name }} {% if employee.age >= 30 %} senior: true {% endif %} skills: {% for skill in employee.skills %} - {{ skill }} {% endfor %} {% endfor %} {% endfor %}""" data = { "departments": { "IT": [ {"name": "Amir", "age": 35, "skills": ["Python", "JavaScript"]}, {"name": "Dina", "age": 28, "skills": ["Java", "SQL"]} ], "HR": [ {"name": "Yasmin", "age": 40, "skills": ["Recruitment", "Training"]} ] } } template = Template(yaml_template) rendered_yaml = template.render(**data) print(rendered_yaml)
Output:
departments: IT: - name: Amir senior: true skills: - Python - JavaScript - name: Dina skills: - Java - SQL HR: - name: Yasmin senior: true skills: - Recruitment - Training
Apply built-in filters
Jinja2 provides various built-in filters to manipulate data.
Filters like upper
, replace
, capitalize
, float
, round
, and lower
are used to transform the input data within the template.
from jinja2 import Template yaml_template = """product: name: {{ name | upper }} description: {{ description | replace("_", " ") | capitalize }} price: {{ price | float | round(2) }} tags: {% for tag in tags %} - {{ tag | lower }}{% endfor %}""" data = { "name": "Egyptian Papyrus", "description": "authentic_ancient_writing_material", "price": 29.99999, "tags": ["HISTORICAL", "Artifact", "Collectible"] } template = Template(yaml_template) rendered_yaml = template.render(**data) print(rendered_yaml)
Output:
product: name: EGYPTIAN PAPYRUS description: Authentic ancient writing material price: 30.0 tags: - historical - artifact - collectible
Using include to embed templates
You can use the include
statement to embed one template within another:
from jinja2 import Environment, FileSystemLoader # Create a Jinja2 environment env = Environment(loader=FileSystemLoader('.')) # Define the main template main_template = """ main_config: {% include 'sub_template.yaml' %} additional_info: created_by: {{ author }} """ # Define the sub-template sub_template = """ name: {{ name }} version: {{ version }} """ # Write the sub-template to a file with open('sub_template.yaml', 'w') as f: f.write(sub_template) # Render the main template template = env.from_string(main_template) rendered_yaml = template.render(name="MyApp", version="1.0", author="Mahmoud") print(rendered_yaml) import os os.remove('sub_template.yaml')
Output:
main_config: name: MyApp version: 1.0 additional_info: created_by: Mahmoud
Import template code and macros
Jinja2 allows you to import macros and template code.
The import
statement allows you to reuse macros and template code across multiple templates:
from jinja2 import Environment, FileSystemLoader # Create a Jinja2 environment env = Environment(loader=FileSystemLoader('.')) # Define a macro in a separate file macro_template = """ {% macro render_person(name, age) -%} name: {{ name }} age: {{ age }} {%- endmacro %} """ # Write the macro to a file with open('macros.yaml', 'w') as f: f.write(macro_template) # Main template that imports and uses the macro main_template = """ {% import 'macros.yaml' as macros %} people: - {{ macros.render_person('Amina', 28) }} - {{ macros.render_person('Hassan', 35) }} """ template = env.from_string(main_template) rendered_yaml = template.render() print(rendered_yaml) import os os.remove('macros.yaml')
Output:
people: - name: Amina age: 28 - name: Hassan age: 35
Mokhtar is the founder of LikeGeeks.com. He is a seasoned technologist and accomplished author, with expertise in Linux system administration and Python development. Since 2010, Mokhtar has built an impressive career, transitioning from system administration to Python development in 2015. His work spans large corporations to freelance clients around the globe. Alongside his technical work, Mokhtar has authored some insightful books in his field. Known for his innovative solutions, meticulous attention to detail, and high-quality work, Mokhtar continually seeks new challenges within the dynamic field of technology.