Basics of Django Templates

What are Django Templates?

Think of Django templates as a scaffolding required to create a complete HTML page. Django templates are nothing more than a text file containing static content and as well as a special dynamic markup specifying some logic, looping, and display of data.

Where to store Django Templates?

Before we start building templates let’s first spend some time to learn how Django searches for templates. Create a new directory called templates inside the blog app located at TGDB/django_project/blog. But why templates directory? Because by default Django searches for templates in the templates directory of every installed app.

If for some reason you want to turn off this behavior open and set 'APP_DIRS' value to False like this:


For now, we don’t have any sound reason to turn off this behavior, so again switch it back to True.

Django treats all of the templates directories as a single directory. That being said, let’s say you have two apps blog and forum with blog/templates/list.html and forum/templates/list.html templates respectively. To Django these two files are same and It will use the template it finds first. Due to this behavior, Django recommends creating a subdirectory inside the templates directory by the name of the app. Create a new subdirectory called blog inside the templates directory. This is where we will store all our templates for the blog app.

A simple Django Template

To make things clear let’s take an example of Django templates. Here is a simple template:

Notice that in addition to HTML code we are using special markup to denote dynamic sections of the page.

Let’s step through the code.

1. Any text that is surrounded by double curly braces ( {{ post_title }} ) is a variable, for example, the code in line 8 i.e <h1>{{ post_title }}</h1> means that output the value of the variable post_title inside h1 tag. So if the value of post_title is "Django Templates" then <h1>Django Templates</h1> will be printed. You might say but how do we specify the value of the variable? Don’t worry we will get to that later.

2. Text surrounded by a single curly brace ({) and the percent sign (%), for example, in line 16 i.e {% for item in item_list %} is called a template tag. A template tag allows us to something very specific. In this case, the for tag works very much like a for loop in Python and is generally used to loop over a list or dictionary.

Just as we can emulate a loop in our templates using the for template tag. We can use if template tag to add logical if statement to our template. In line 21, we have an if template tag.

Here is how it works:

First, the value of variable comments is evaluated. If it is True then <p>This post has some comments</p> will be printed otherwise, <p>This post has no comments</p> will be printed.

3. Finally, in line 10, we have used a filter i.e {{ author|title }}. A filter is a way to format the output of the variable. We specify the filter using the pipe character (|) followed by the name of the filter after the variable name. If the value of variable author is "bob" then because of the title filter "Bob" will be printed instead of "bob". The title filter converts the first character of every word in the string to uppercase and remaining characters to the lowercase.

Django templates have access to many other filters; we will discuss some important ones in lesson
Templates filter in Django. In addition to built-in filters, you can also create your own filters.

Using Django Template System

The template engine is software which loads and renders a template into markup. Each template engine defines a language to create templates. We have already seen some part of this language in the previous section i.e {{ post_title }} and {% if comments %}, Remember these ?? The template engine provided by Django is called **Django Template Language** or **DTL** for short. Before Django 1.8, DTL was the only option. But with Django 1.8 and later we can use an external template engine like Jinja2. However, if you don’t have any sound reason to use Jinja2 just stick to DTL and you would be fine. Throughout this tutorial, we would be using DTL only.

Before we start to use templates in our views let’s dig in a little deeper to understand the mechanics of how they work. Here is the basic workflow involved in using Django templates:

  1. Create a new Template object by passing the content of the template as a raw string.
  2. Call render() method on template object with a given set of variables. The render() method returns a fully rendered code after evaluating all variables and template tags.

To create Template objects open interactive Python shell by issuing the following command.

Noticed something different here? Well, here we are starting Python shell using the python shell instead of just python. But why? Because in addition to invoking Python interpreter python shell imports bare minimum of Django to work with. We will refer to this shell as Django shell.

Okay, let’s create some Template objects now.

Here is how the above code works.

  1. In line 2, we are importing template module from the django package.
  2. The template module has Template class. In line 3, we are creating a new Template object by passing a raw string to the constructor of Template class.
  3. Our template string consists of one variable. To pass the value to this variable we use Context class. Instantiate Context class by passing a dictionary mapping variable names to variable values.
  4. Finally, to render the template call render() method with Context object as a parameter.

Once the template is loaded, it can be rendered as many times as you want to without reloading.

But what would happen if we don’t provide any value to the Context constructor? In that case, you would not get any error message instead Django will print nothing. This may sound frustrating at first but it is very useful because, in a real-world application, it’s unacceptable for a website to start throwing errors just because of a missing value.

The keys in the Context dictionary is case sensitive, so Django will print nothing if the variable name is slightly different from the expected variable name in the template.

Therefore it is very important to make sure that the name of keys in the Context dictionary is exactly the same as in templates.

Context Variable Lookup

So far we have been passing simple data mainly strings to our templates. However, Django template system can easily handle complex data structures like list, dictionary or even objects. The key to accessing these complex data structures inside the templates is to use the dot character (.). This can be best described by some examples.

Passing a dictionary

Similarly, we can use the dot operator (.) to access objects attributes.

Passing an object

In the above example, we are using a built-in class. The same behavior is true for custom classes we create.

Calling methods

Using the dot operator (.) you can also call methods of an object inside the templates, but remember that while doing so we do not include parentheses ().

It is important to note that we can only call methods inside the template which do not require any arguments.

Passing a list

We can also access elements of a list using the dot (.) operator followed by the index position. Remember that lists in python are 0 indexed.

Although, we can use a negative index in Python to access elements of a list, but this functionality is not available in Django templates.

Order of the dot lookups

The dot (.) character has a special meaning inside the templates. A dot (.) after a variable name signifies lookup. When Django template system encounters a dot (.) after a variable name, it tries the perform lookups, in this particular order.

  1. Dictionary lookup – var.['key']
  2. Attribute lookup – var.key
  3. Method call lookup – var.key()
  4. List-index lookup – var.1

The template system uses the first lookup that works. It’s is short-circuit logic. In other words, we can chain lookups one after another. For example: {{ person.first_name.capitalize }}, since lookups work using short-circuit logic first person.first_name is evaluated followed by the capitalize() method.

1 thought on “Basics of Django Templates

  1. Awesome tutorial so far.

    I’m probably on a different Django version, but I’m seeing an error “TypeError context must be a dict rather than Context” on the line

    c = template.Context({‘now’:now}).

    It goes away if I render it instead of creating the context.

    html = t.render({‘now’:now})

    Just FYI in case anyone else runs into this too

Leave a Comment

%d bloggers like this: