Configuration & Template Automation
Structured Data as Template Input
What you'll learn
- How to model a device's multiple VLANs as a list of dicts
- How to access nested list/dict values inside a Jinja2 template with dot and index notation
- Why a single hostname/description pair was never the hard case this module cares about
Listen to a guided explanation of this lesson.
Spoken narration isn't supported in this browser.
One value vs. many
Lesson 2's template filled in a hostname and a description — one value each, known in advance. Real device configuration is rarely that simple. A single switch might need three, five, or a dozen VLANs configured, each with its own ID and name. That's not "one more variable" — it's a list of related values, the same shape "Lists & Dictionaries for Network Data" already covered.
device = {
"hostname": "SW1",
"vlans": [
{"id": 10, "name": "USERS"},
{"id": 20, "name": "VOICE"},
{"id": 30, "name": "MGMT"},
],
}Nothing new here — a dict whose 'vlans' key holds a list of dicts. This is the exact 'list of dictionaries' shape from Python Lesson 3, and the same shape structured inventory has used since Network Automation Fundamentals.
Not a new data concept — a new use for one
This isn't teaching a new way to model data. It's the same list-of-dicts shape you've used since early in this curriculum, now used specifically as a template's input instead of plain program logic.
- hostnameone known value
- descriptionone known value
- Fine for Lesson 2's single interface block
- vlans: [ ... ]a list — any number of items
- Each item its own dictid, name
- What a real device's VLANs actually look like
Accessing nested data inside a template
A template can reach into that structure the same way Python does — dot notation for a dict's keys, and [index] for a list's position:
from jinja2 import Template
device = {
"hostname": "SW1",
"vlans": [
{"id": 10, "name": "USERS"},
{"id": 20, "name": "VOICE"},
{"id": 30, "name": "MGMT"},
],
}
template = Template("vlan {{ device.vlans[1].id }}\n name {{ device.vlans[1].name }}")
print(template.render(device=device))device.vlans[1] reaches the second VLAN dict (index 1, the middle one); .id and .name then reach into that dict — dot notation works for dict keys inside a Jinja2 expression, not just object attributes.
This prints:
vlan 20
name VOICEIndex 1 is VOICE — the second item in the list (0 = USERS, 1 = VOICE, 2 = MGMT), same zero-based indexing Python itself uses.
The awkward part this sets up
Writing device.vlans[0], then device.vlans[1], then device.vlans[2] by hand doesn't scale any better than the hardcoded strings Lesson 1 started with — it just moved the repetition from Python to the template. A device with a dozen VLANs would need a dozen manually-indexed lines. What's actually needed is a way to say "do this once, for every item in the list" — which is exactly what Lesson 4 introduces.
Key takeaways
- A device's multiple VLANs are modeled as a list of dicts — the same 'list of dictionaries' shape from Python Lesson 3, now used as template input.
- Inside a Jinja2 template, dot notation reaches a dict's keys and [index] reaches a list's items — the same zero-based indexing Python uses.
- This is not a new data concept — it's a new use for a data shape this curriculum has used since Network Automation Fundamentals.
- Manually indexing every item in a list doesn't scale to devices with a different number of VLANs — the exact problem Lesson 4's loop solves.
Done with this lesson?
Next lesson
Loops and Conditions for Repeated Configuration