Django Template for Loop: Display Lists and Objects

Recommended preparation: set up a Django project and read the Django tutorial overview before trying the code.

A Django template uses {% for item in items %} to repeat markup for a list or QuerySet. The examples begin with a plain Python list, then show database records from the same Student model used throughout this section.

views.py — pass employee records to the template

from django.shortcuts import render

def employees(request):
    people = [
        {"id": 123, "name": "Ravi", "job": "Manager"},
        {"id": 124, "name": "Raju", "job": "Driver"},
        {"id": 125, "name": "Kiran", "job": "Store Keeper"},
    ]
    return render(request, "employees.html", {"people": people})

For display-only records, a list of dictionaries is sufficient. When records must be saved in a database, use a real Django model with models.CharField and other field definitions instead of assigning Python types such as str to class attributes.

On this page — Show page sectionsHide page sections

Write the Django template loop

templates/employees.html

<ul>
{% for person in people %}
  <li>{{ person.id }} — {{ person.name }} ({{ person.job }})</li>
{% empty %}
  <li>No employees found.</li>
{% endfor %}
</ul>

Expected output

123 — Ravi (Manager)
124 — Raju (Driver)
125 — Kiran (Store Keeper)

Configure the URL

my_app/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path("employees/", views.employees, name="employees"),
]

Display real database rows

students/models.py — database-backed Student model

from django.db import models

class Student(models.Model):
    name = models.CharField(max_length=100)
    cl = models.CharField(max_length=20, db_column="class")
    mark = models.PositiveSmallIntegerField()
    gender = models.CharField(max_length=20)

    def __str__(self):
        return self.name

students/views.py

from django.shortcuts import render
from .models import Student

def student_list(request):
    students = Student.objects.order_by("id")
    return render(request, "students/list.html", {"students": students})

students/templates/students/list.html

<table>
  <thead><tr><th>ID</th><th>Name</th><th>Mark</th></tr></thead>
  <tbody>
  {% for student in students %}
    <tr><td>{{ student.id }}</td><td>{{ student.name }}</td><td>{{ student.mark }}</td></tr>
  {% empty %}
    <tr><td colspan="3">No student records yet.</td></tr>
  {% endfor %}
  </tbody>
</table>

Use loop counters and conditionals

Template: a counter and an if condition

{% for student in students %}
  <p>{{ forloop.counter }}. {{ student.name }}
     {% if student.mark >= 50 %}(Pass){% else %}(Review){% endif %}
  </p>
{% endfor %}

forloop.counter starts at 1; forloop.counter0 starts at 0. Django template syntax is not Python syntax: use template tags rather than Python list comprehensions inside HTML.

Nested loops

Nested template loops

{% for week in weekly_tasks %}
  <h3>Week {{ forloop.counter }}</h3>
  <ul>
  {% for task in week %}
    <li>{{ task }}</li>
  {% endfor %}
  </ul>
{% endfor %}

Filtering and performance

Do filtering and ordering in the view or model layer, not with complex template conditions. For database lists, use QuerySet filters and slicing and consider pagination for large tables. Templates should focus on presentation.

View: only the first 20 passing students, alphabetically

students = Student.objects.filter(mark__gte=50).order_by("name")[:20]

Common errors

  • TemplateSyntaxError: every {% for %} needs a matching {% endfor %}.
  • Nothing appears: confirm the view context key matches the loop variable.
  • N+1 database queries: use select_related() or prefetch_related() when accessing related objects.
  • Unsafe output: keep template autoescaping enabled; do not mark untrusted strings as safe.

For Python’s own iteration statements, see the Python for-loop tutorial. Django templates use a restricted presentation language rather than executing general Python expressions.

Frequently asked questions

How do I show a message when a list is empty?

Use the {% empty %} block inside {% for %} to display fallback markup.

Can I iterate through Django QuerySets?

Yes. QuerySets are iterable and commonly passed to templates through context dictionaries.

Should I create a Django model just to display three hard-coded objects?

No. A list of dictionaries or simple objects is suitable until you need persistent database records.

Previous: Query string parameters

Next: CSS, JavaScript, jQuery and static files

Browse the complete Django tutorial series.

Additional references

Back to top ↑




Subscribe to our YouTube Channel here



plus2net.com







Python Video Tutorials
Python SQLite Video Tutorials
Python MySQL Video Tutorials
Python Tkinter Video Tutorials
✖
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
© 2000-2026 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer