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 djangobin app located at djangobin/django_project/djangobin. 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 settings.py and set 'APP_DIRS' value to False like this:

djangobin/django_project/django_project/settings.py

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. This means that if 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 (depends on the order of apps listed in INSTALLED_APPS setting). Due to this behavior, Django recommends creating a subdirectory inside the templates directory by the name of the app. Create a new subdirectory called djangobin inside the templates directory. This is where we will store all our templates for the djangobin app.

A simple Django Template

To make things clear let’s take an example of Django template. The following listing shows a simple template for the blog post:

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 ( <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 %} tag. We can use {% if %} tag to add logical if statement to our templates. 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 that, you can also create your own filters.

Using Django Template System

The template engine is program 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, for example, {{ post_title }}, {% if comments %} etc. 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.

Let’s try creating some Template objects in the Django shell.

Here is how the above code works.

  1. In line 8, we are importing template module from the django package.
  2. The template module has Template class. In line 9, 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 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 same as that of variables in the 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 behaviour is true for 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.

We can also chain lookups one after another. For example:

Here person.first_name is evaluated first then the capitalize() method will be applied on the result.

Leave a Comment