Django templates are HTML files with extra syntax to allow using variables, loops, and other control structures. When a view calls the render() function, it passes data into the template and the template generates the HTML to show to the user. This is a very similar concept in many MVC and MVT web frameworks. Django makes use of a built-in backend for its own template system that is called the Django Template Language or DTL. Since this is the default template system that Django ships with and makes use of, that is the one that we will learn about in this Django template tutorial.
Django Template Syntax
The syntax for Django templates has three pieces. These are variables, tags, and variables with filters.
{{ variable }}
The value of a variable is displayed when the variable name is used inside of double curly braces. This is a form of interpolation.{% tag %}
Template tags are enclosed in curly braces with percent signs and are used for for looping, if else constructs, structural elements, as well as some control logic.{{ variable|filter }}
In Django templates, a variable can also have a pipe character after it to use a template filter. Template filters take a string as input and return a string as output.
Template filters work in a similar way to the pipe in shell scripting. Filters are used for data formattings like setting text into title or uppercase.
Template Variable Example
As an example of using variables in a template, we can look at the dog_detail.html template we created in the last tutorial. Depending on the URL we visit, a different Dog is passed into the template. Here is an h2 tag and we use the double braces to render the dog’s name attribute. The result is the string Winnie inside of an h2 tag.
djangodogs/templates/dog_detail.html
<h2>{{ dog.name }}</h2>
result
<h2>Winnie</h2>
How to loop over data in Django Templates
If you have several items you need to display, you’ll need the ability to loop over the collection to show each item. This is often the case in a home template. In our case, we have several Dogs we want to display when visiting the home page. In this example, we have a query set of Dog instances in the variable dogs
that the home view is passing into the template. We use the for
template tag to loop over each dog
instance. Note that the endfor
tag at the end of this snippet is necessary to mark the end of the loop. If it is left off, you will get an error. Inside the loop, we can use the dog
variable, and here, we are rendering the dog’s name using dog.name
in an h1 tag. The result is an h1 tag for each dog that’s in the database, each showing their name.
djangodogs/templates/home.html
<body>
{% for dog in dogs %}
<h1>{{ dog.name }}</h1>
{% endfor %}
</body>
result
<h1>Winnie</h1> <h1>Mosely</h1> <h1>Bella</h1>
URL Template Tag
Some template tags don’t have a corresponding end tag and just render a string instead and the url
tag is an example of this. This tag takes the name of the url-pattern as an argument and returns the path to that pattern. This is where the name argument of a url-pattern becomes useful. In the code below, the url tag renders the path to the dog detail view for whatever id is given. So depending on the id provided, the url may translate to /dogs/1/, /dogs/2/, /dogs/3/, and so on. You might be asking why the url tag is used instead of just hard-coding the href for the home view and for the dog detail links. What the url tag provides is a bit of future-proofing. By using the url tag instead of hard coding, we can decide to change am url-pattern later on and links we use in our templates will still work.
<body>
{% for dog in dogs %}
<a href="{% url 'dog_detail' dog.id %}">
<h1>{{ dog.name|capfirst }}</h1>
</a>
{% endfor %}
</body>
result
<body> <a href="/dogs/1/"> <h1>Winnie</h1> </a> <a href="/dogs/2/"> <h1>Mosely</h1> </a> <a href="/dogs/3/"> <h1>Bella</h1> </a> </body>
Template Filters
Template filters allow output formatting for the variables that are passed into templates to be rendered on the page. Now in our case, we had already added some dogs to the database with the first letter being capitalized. So when we output the dogs, we see their name has a capital letter shown above. A template filter is simply a string after the pipe character. We can make the dog names all lower case with the lower template filter. Here is an example of that.
<body>
{% for dog in dogs %}
<a href="{% url 'dog_detail' dog.id %}">
<h1>{{ dog.name|lower }}</h1>
</a>
{% endfor %}
</body>
</body>
result
<body> <a href="/dogs/1/"> <h1>winnie</h1> </a> <a href="/dogs/2/"> <h1>mosely</h1> </a> <a href="/dogs/3/"> <h1>bella</h1> </a> </body>
Let’s try another example of a template filter. This time we will use the upper filter, which should format our variables to all upper case.
<body>
{% for dog in dogs %}
<a href="{% url 'dog_detail' dog.id %}">
<h1>{{ dog.name|upper }}</h1>
</a>
{% endfor %}
</body>
</body>
result
<body> <a href="/dogs/1/"> <h1>WINNIE</h1> </a> <a href="/dogs/2/"> <h1>MOSELY</h1> </a> <a href="/dogs/3/"> <h1>BELLA</h1> </a> </body>
There are a lot of template filters available in Django. Some of them include add, addslashes, capfirst, center, cut, date, default, default_if_none, dictsort, dictsortreversed, divisibleby, escape, escapejs, filesizeformat, first, floatformat, force_escape, get_digit, iriencode, join, json_script, last, length, length_is, linebreaks, linebreaksbr, linenumbers, ljust, lower, make_list, phone2numeric, pluralize, pprint, random, rjust, safe, safeseq, slice, slugify, stringformat, striptags, time, timesince, timeuntil, title, truncatechars, truncatechars_html, truncatewords, truncatewords_html, unordered_list, upper, urlencode, urlize, urlizetrunc, wordcount, wordwrap, and yesno. To learn how all of these work you can check the Django template tags and filters reference.
Django Template Inheritance
Template inheritance is a feature in Django templates that use the extends
and block
tags. It’s never good to repeat code over and over if you don’t have to and in Django, we can use a base template with the elements that every template will use, such as meta tags, any global CSS or JavaScript, or other structural elements that we don’t want to redeclare in every template. In this example, we’re defining some HTML boilerplate in the template file called base.html. In its body tag, we have a block template tag to provide a place for child templates to define their unique content.
base.html
<!DOCTYPE html>
<html>
<head>
<!-- meta tags, etc.. -->
</head>
<body>
{% block content %}
{% endblock content %}
</body>
</html>
Now we can adjust the home template and make use of the extends
tag with base.html as its parameter. This configures the home template to use the base.html template as its parent. The extends declaration has to be the first line of the template. This is how we ensure that any block tags in this template will be used to indicate an area of content that will override and fill-in sections of the parent. In the example, we’re overriding the block called content. When rendered, the home template will have the HTML from the base template, and its body tag will be filled with whatever’s placed in the content block. Here it is in action.
home.html
{% extends 'base.html' %}
{% block content %}
{% for dog in dogs %}
<a href="{% url 'dog_detail' dog.id %}">
<h1>{{ dog.name }}</h1>
</a>
{% endfor %}
{% endblock content %}
result
<!DOCTYPE html> <html> <head> <!-- meta tags, etc.. --> </head> <body> <a href="/dogs/1/"> <h1>Winnie</h1> </a> <a href="/dogs/2/"> <h1>Mosely</h1> </a> <a href="/dogs/3/"> <h1>Bella</h1> </a> </body> </html>
Using Bootstrap In Django Template
Now that we know how to implement a base.html template that can contain any repetitive boilerplate code, let’s add some Bootstrap styling to our examples to make them look a little better than raw Html. First, we can add the starter template markup for bootstrap into the base.html file. Note the block and endblock tags that show where dynamic content will be inserted.
base.html
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body class="container mt-4">
{% block content %}
{% endblock content %}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
</body>
</html>
Now in our home.html file, we can use that extends
tag to inherit all of the markup from the base.html file. Since that file has links to the Bootstrap CSS CDN, we can make use of Bootstrap classes on our Html elements in the home.html template.
home.html
{% extends 'base.html' %}
{% block content %}
{% for dog in dogs %}
<div class="card mb-4">
<div class="card-body">
<h4 class="card-title">{{ dog.name }}</h4>
<h6 class="card-subtitle mb-2 text-muted">Dog number {{ dog.id }}</h6>
<p class="card-text">{{ dog.name }} is a wonderful dog!</p>
<a href="{% url 'dog_detail' dog.id %}" class="btn btn-primary">Learn more about {{ dog.name }}</a>
</div>
</div>
{% endfor %}
{% endblock content %}
We can also update the dog_detail.html template so that when viewing an individual Dog, the styling looks nice.
dog_detail.html
{% extends 'base.html' %}
{% block content %}
<div class="jumbotron">
<h1 class="display-4">Hello, {{ dog.name }}!</h1>
<p class="lead">The breed of this dog is {{ dog.breed }}</p>
<p>Description: {{ dog.description }}</p>
</div>
{% endblock content %}
How To Add Static Files
We have a decent little dog website going at this point, but we haven’t yet talked about how to add our own CSS, Images, or JavaScript files. These are what are known as static files in the realm of a web project. In any web-based application, you will need to include static files. So to include static files in our Django project, we can add a new folder in the root directory of the project named static. Inside of that folder, we can create more folders as needed. In most scenarios, you’ll have a folder for your images, one for your CSS files, and one for any JavaScript files to include.
Configuring STATICFILES_DIRS
Static files can be configured per application, and also per project. In our case, we are going to see how to add static files to the project. In this way, those static files can be shared across applications if you like. To configure this, we go into djangotutorial/settings.py and add the following code.
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
With the above settings in place, we’ll be able to easily access the files and folders in the static directory.
{% load static %}
Now, let’s adjust the base.html file that all other template files inherit from. We can remove the CDN links we had earlier, and put references to our static files in place.
base.html
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
{% load static %}
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'css/main.css' %}">
<title>Hello, world!</title>
</head>
<body class="container mt-4">
{% block content %}
{% endblock content %}
</body>
</html>
home.html
In the home.html file, we also use the static keyword to load an image.
{% extends 'base.html' %}
{% block content %}
{% load static %}
<img class="img-custom" src="{% static "images/dog.png" %}" alt="My image">
{% for dog in dogs %}
<div class="card mb-4">
<div class="card-body">
<h4 class="card-title">{{ dog.name }}</h4>
<h6 class="card-subtitle mb-2 text-muted">Dog number {{ dog.id }}</h6>
<p class="card-text">{{ dog.name }} is a wonderful dog!</p>
<a href="{% url 'dog_detail' dog.id %}" class="btn btn-primary">Learn more about {{ dog.name }}</a>
</div>
</div>
{% endfor %}
{% endblock content %}
result
<!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="stylesheet" href="/static/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/css/main.css"> <title>Hello, world!</title> </head> <body class="container mt-4"> <img class="img-custom" src="/static/images/dog.png" alt="My image"> <div class="card mb-4"> <div class="card-body"> <h4 class="card-title">Winnie</h4> <h6 class="card-subtitle mb-2 text-muted">Dog number 1</h6> <p class="card-text">Winnie is a wonderful dog!</p> <a href="/dogs/1/" class="btn btn-primary">Learn more about Winnie</a> </div> </div> <div class="card mb-4"> <div class="card-body"> <h4 class="card-title">Mosely</h4> <h6 class="card-subtitle mb-2 text-muted">Dog number 2</h6> <p class="card-text">Mosely is a wonderful dog!</p> <a href="/dogs/2/" class="btn btn-primary">Learn more about Mosely</a> </div> </div> <div class="card mb-4"> <div class="card-body"> <h4 class="card-title">Bella</h4> <h6 class="card-subtitle mb-2 text-muted">Dog number 3</h6> <p class="card-text">Bella is a wonderful dog!</p> <a href="/dogs/3/" class="btn btn-primary">Learn more about Bella</a> </div> </div> </body> </html>
Learn More About Django Templates
- The Official DTL Docs (docs.djangoproject.com)
- Django Templates (djangobook.com)
- Django Templates at Read the Docs (django.readthedocs.io)
- How to configure Django Templates (djangocentral.com)
- Performance of Django Templates (dyspatch.io)
- How to loop in Django Templates (pythoncircle.com)
- Django Template Fiddle (pythoncircle.com)
- Best Practices for Django Templates (kite.com)
- Traversing a Dictionary in Django Template Language (dudepare.github.io)
Django Template Summary
In this tutorial, we had a look at the Django template language which is Django’s own template system. There are other third party template systems available for working with Django, but it’s probably best to just use DTL as it is the standard for Django. Using DTL will make it much easier to create apps that will be pluggable to other projects, and help you create more reusable templates.