Django
template
model instance
field iteration
Python

Iterate over model instance field names and values in template

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Django templates are intentionally limited, so iterating over a model's fields is usually easier if you prepare the data in Python first. That keeps the template simple and avoids pushing reflection logic into the presentation layer.

Build Field Rows in the View

The most maintainable pattern is to inspect the model instance in the view, convert each field into a display-friendly structure, and pass that structure to the template.

python
1from django.shortcuts import get_object_or_404, render
2from .models import Book
3
4
5def build_field_rows(instance):
6    rows = []
7    for field in instance._meta.fields:
8        rows.append(
9            {
10                "name": field.name,
11                "label": field.verbose_name,
12                "value": getattr(instance, field.name),
13            }
14        )
15    return rows
16
17
18def book_detail(request, pk):
19    book = get_object_or_404(Book, pk=pk)
20    return render(
21        request,
22        "books/detail.html",
23        {
24            "book": book,
25            "field_rows": build_field_rows(book),
26        },
27    )

The template now receives a list of dictionaries that are easy to render. You keep the model introspection in Python, where it is easier to test and easier to customize later.

Render the Prepared Data in the Template

Once the view has prepared field_rows, the template can stay almost completely declarative.

django
1<table>
2  <tbody>
3    {% for row in field_rows %}
4      <tr>
5        <th>{{ row.label|capfirst }}</th>
6        <td>{{ row.value }}</td>
7      </tr>
8    {% endfor %}
9  </tbody>
10</table>

This is usually all you need. If the model changes over time, the template adapts automatically because the view builds the list dynamically.

Use a Template Filter When Multiple Templates Need It

If you need the same behavior in many templates, move the field extraction logic into a custom template filter or simple tag. The core idea stays the same: do the introspection in Python, not in raw template logic.

python
1from django import template
2
3register = template.Library()
4
5
6@register.filter
7def model_fields(instance):
8    rows = []
9    for field in instance._meta.fields:
10        rows.append((field.verbose_name, getattr(instance, field.name)))
11    return rows

Then in the template:

django
1{% load model_extras %}
2
3<ul>
4  {% for label, value in book|model_fields %}
5    <li><strong>{{ label|capfirst }}:</strong> {{ value }}</li>
6  {% endfor %}
7</ul>

This is a good choice when the display pattern is repeated in many places and you want to avoid duplicating helper code across views.

Decide Which Fields Should Be Shown

Blindly iterating over instance._meta.fields is not always the final answer. Real applications often hide IDs, timestamps, internal flags, or foreign key internals. The helper can easily filter those out.

python
1def build_public_field_rows(instance):
2    hidden = {"id", "created_at", "updated_at"}
3    rows = []
4    for field in instance._meta.fields:
5        if field.name in hidden:
6            continue
7        rows.append(
8            {
9                "label": field.verbose_name,
10                "value": getattr(instance, field.name),
11            }
12        )
13    return rows

That small amount of filtering gives you a much cleaner UI than dumping every field automatically.

Why Not Do Everything Inside the Template

Django templates do not support arbitrary Python expressions, and that is deliberate. It keeps presentation code safe and easy to review. If you try to make the template walk _meta, format values, skip hidden fields, and resolve relationships, the result becomes harder to read than the view code you were trying to avoid.

The view or a template tag is the right layer for this work because it can normalize dates, transform booleans into human-friendly labels, and handle missing values consistently.

Common Pitfalls

  • 'instance._meta.fields includes database fields, but not every relationship type you may want to display.'
  • Dumping raw values can expose internal IDs or admin-only data, so filter the list deliberately.
  • Templates that do too much introspection become harder to test and harder for teammates to maintain.
  • Foreign keys may render as numeric IDs unless the related model defines a useful string representation.

Summary

  • Prepare field names and values in Python, then pass a simple list to the Django template.
  • 'instance._meta.fields is the usual starting point for model field iteration.'
  • A custom template filter is useful when multiple templates need the same behavior.
  • Filter and format fields intentionally instead of rendering every database column by default.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.