Skip to main content

Loops

In a template you can execute the equivalent of Python's for loop, which is ideal for building HTML lists or tables from a Python collection, as we had done in the previous chapter from the courses() view. For example:

def index(request: HttpRequest) -> HttpResponse:
ctx = {
"students": ["John", "Sophie", "Matthew"]
}
return render(request, "myapp/index.html", ctx)

In the template:

<html>
<h1>List of students</h1>
<ul>
{% for student in students %}
<li>{{ student }}</li>
{% endfor %}
</ul>
</html>

Here the for loop has the same meaning as in Python: for each element of the students collection (which has to be in the context), include in the template what is between {% for … %} and {% endfor %}. Thus, this code generates the following HTML:

Source of Rendered Template

Now that we know this syntax, we can rewrite our courses view like this:

def courses(request: HttpRequest) -> HttpResponse:
conn = sqlite3.connect("courses.db")
cursor = conn.cursor()
cursor.execute("SELECT name, enrolled_students FROM courses")
courses = cursor.fetchall()
conn.close()
ctx = {"courses": courses}
return render(request, "myapp/courses.html", ctx)

And in a new file templates/myapp/courses.html:

{% load static %}
<html>
<head>
<title>Courses List</title>
<link rel="stylesheet" type="text/css" href='{% static "myapp/styles.css" %}'>
</head>
<table class="courses-table">
<thead>
<tr>
<th>Course</th>
<th>Students</th>
</tr>
</thead>
{% for name, enrolled_students in courses %}
<tr>
<td>{{ name }}</td>
<td>{{ enrolled_students }}</td>
</tr>
{% endfor %}
</table>
</html>