django
django-templates
python
nested-dictionary
web-development

how to iterate through dictionary in a dictionary in django template?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Django templates can iterate nested dictionaries, but the syntax is intentionally limited so that presentation logic stays simple. The important rule is to prepare data in the view and keep the template focused on display. Once the structure is in the context, nested loops with .items are usually enough.

Basic Nested Dictionary Example

Suppose your view passes this context:

python
1def dashboard(request):
2    context = {
3        "report": {
4            "users": {"active": 12, "inactive": 3},
5            "orders": {"pending": 5, "shipped": 8},
6        }
7    }
8    return render(request, "dashboard.html", context)

In the template, iterate over the outer dictionary first, then the inner dictionary.

django
1{% for section, values in report.items %}
2  <h2>{{ section }}</h2>
3  <ul>
4    {% for key, value in values.items %}
5      <li>{{ key }}: {{ value }}</li>
6    {% endfor %}
7  </ul>
8{% endfor %}

This is the standard pattern for nested dictionary display.

Keep Complex Reshaping Out of Templates

Django templates support iteration, but they are deliberately weak at arbitrary data manipulation. If your structure needs filtering, sorting, flattening, or renaming, do it in the view first.

Bad idea:

  • complicated nested conditionals in template
  • assumptions about missing keys everywhere
  • business logic spread across HTML

Better idea:

python
1def dashboard(request):
2    raw = {
3        "users": {"active": 12, "inactive": 3},
4        "orders": {"pending": 5, "shipped": 8},
5    }
6
7    sections = [
8        {"name": name, "rows": values.items()}
9        for name, values in raw.items()
10    ]
11
12    return render(request, "dashboard.html", {"sections": sections})

Then the template becomes even simpler.

Handle Missing or Optional Inner Dictionaries

If inner values might be missing or empty, normalize them in the view so the template does not need defensive logic everywhere.

python
1def dashboard(request):
2    raw = {
3        "users": {"active": 12},
4        "orders": None,
5    }
6
7    normalized = {
8        name: values or {}
9        for name, values in raw.items()
10    }
11
12    return render(request, "dashboard.html", {"report": normalized})

That keeps the template predictable.

Order and Display Considerations

Dictionaries preserve insertion order in modern Python, but if display order matters, do not rely on accident. Sort or build the structure explicitly in the view.

python
1ordered_rows = {
2    section: dict(sorted(values.items()))
3    for section, values in report.items()
4}

This is often better than trying to force ordering logic into the template layer.

When a Custom Template Filter Helps

If the nested access pattern repeats across templates, a small custom template filter or inclusion tag can improve readability. But use that only when the logic is truly presentation-related. If the transformation is business logic, keep it in Python view or service code instead.

Example with Table-Like Output

Nested dictionaries are often displayed as grouped tables rather than unordered lists. The same iteration pattern still works:

django
1{% for section, values in report.items %}
2  <h3>{{ section }}</h3>
3  <table>
4    {% for key, value in values.items %}
5      <tr>
6        <th>{{ key }}</th>
7        <td>{{ value }}</td>
8      </tr>
9    {% endfor %}
10  </table>
11{% endfor %}

The structure is simple, and the data preparation still belongs in the view.

Common Pitfalls

  • Trying to perform complex data reshaping directly in the template.
  • Forgetting to call .items on both the outer and inner dictionaries.
  • Passing inconsistent nested structures and then compensating with template hacks.
  • Assuming display order without preparing ordered data in the view.
  • Moving business logic into templates just to “avoid writing Python.”

Summary

  • Use nested {% for %} loops with .items to iterate dictionaries inside dictionaries.
  • Prepare and normalize the structure in the view before rendering.
  • Keep sorting and transformation logic out of the template whenever possible.
  • Use custom tags only for reusable presentation concerns.
  • Treat Django templates as a rendering layer, not a data-processing engine.

Course illustration
Course illustration

All Rights Reserved.