Skip to main content

Introduction to the Template System

In the previous chapter we saw how to construct HTML code from a view and return it as the content of a response via the django.http.HttpResponse class. However, this procedure of including HTML code within Python code becomes problematic when you start working with real web applications, where HTML code is often voluminous and some of it is repeated on many pages. Furthermore, it is not a good practice to mix two very different concepts of an application: the logical component (Python code) and the graphical component (HTML).

In principle this could be solved by moving the HTML code to a separate file and then loading it from a view. For example, in myapp/views.py:

from pathlib import Path

# ...

def index(request: HttpRequest) -> HttpResponse:
response = HttpResponse(Path("myapp/index.html").read_text("utf8"))
return response

Having created a myapp/index.html file with something like:

<html>
<strong>Hello</strong>, <em>world</em>!
</html>

Thus, you keep these two components separate and your application is much more organized. The disadvantage of this procedure is that you lose the possibility of generating HTML code from Python data, such as we did with the HTML table in the courses view:

def courses(request: HttpRequest) -> HttpResponse:
# ...
for name, enrolled_students in cursor.fetchall():
html += f"""
<tr>
<td>{name}</td>
<td>{enrolled_students}</td>
</tr>
"""

To solve this problem, Django and other web frameworks include a template system. These systems allow you to create HTML code files (and other formats) in which you are able to include small portions of Python code. In the case of Django, you can not use strictly Python code, but rather a small dialect designed for this purpose, called Django Template Language.

Let's look at an example reimplementing the above index() view code using the template system. First, create the myapp/templates/myapp/index.html file (note that the templates and templates/myapp/ directories are not created by the startapp command, so it must be done manually) with the same content as before (or just move the file to that location):

<html>
<strong>Hello</strong>, <em>world</em>!
</html>

Second, change the index() function to look like this:

def index(request: HttpRequest) -> HttpResponse:
return render(request, "myapp/index.html")

We hadn't used the render() function yet, so import it at the beginning of views.py:

from django.shortcuts import render

Now visit http://127.0.0.1:8000/myapp/ and you will see:

Rendered Template

It's not much different than what we had before, but the important thing is that the HTML code is being loaded from the myapp/templates/myapp/index.html file.

Let's make some clarifications regarding the render() function. As the first argument we pass the request that we received as an argument in the view. The second argument is a path (relative to the templates/ folder) to the template containing our HTML code. Actually, this function internally reads the contents of the file, processes it with Django's template system, and returns the result as an instance of django.http.HttpResponse.

In the next section we will begin to make use of some of the features provided by the template system.