Skip to main content

Django Template Language

Django Template Language (DTL) is a powerful and flexible text-based template system that enables you to separate HTML presentation from Python code. As a beginner Django developer, understanding DTL is crucial for creating dynamic web pages that can display data from your backend.

Introduction to Django Template Language

Django templates are text files designed to separate the presentation logic from the business logic of your application. They can contain HTML markup as well as special syntax for inserting dynamic content and applying programming-like logic. The Django Template Language provides constructs to:

  • Display variables sent from the view
  • Apply filters to modify variables
  • Execute control logic like loops and conditionals
  • Extend and include other templates

Let's dive into each of these features to gain a complete understanding of DTL.

Variables in Templates

Variables are the most fundamental concept in any template language. In DTL, you can display variables by enclosing them in double curly braces.

Basic Variable Display

python
# views.py
def my_view(request):
return render(request, 'my_template.html', {'name': 'John', 'age': 25})
html
<!-- my_template.html -->
<h1>Hello, {{ name }}!</h1>
<p>You are {{ age }} years old.</p>

Output:

html
<h1>Hello, John!</h1>
<p>You are 25 years old.</p>

Accessing Object Attributes and Dictionary Keys

You can access attributes of objects, items in dictionaries, and elements in lists using dot notation:

python
# views.py
def my_view(request):
context = {
'person': {
'name': 'John',
'age': 25
},
'fruits': ['apple', 'banana', 'cherry']
}
return render(request, 'my_template.html', context)
html
<!-- my_template.html -->
<p>Name: {{ person.name }}</p>
<p>Age: {{ person.age }}</p>
<p>First fruit: {{ fruits.0 }}</p>

Output:

html
<p>Name: John</p>
<p>Age: 25</p>
<p>First fruit: apple</p>

Template Filters

Filters allow you to modify variables for display. They are applied using the pipe symbol (|).

html
<!-- Using filters -->
<p>Name: {{ name|upper }}</p>
<p>Bio: {{ bio|truncatewords:10 }}</p>
<p>Joined: {{ join_date|date:"F j, Y" }}</p>

Common Filters

Here are some commonly used filters:

FilterDescriptionExample
lowerConvert to lowercase{{ name |lower }}
upperConvert to uppercase{{ name |upper }}
titleCapitalize first letter of each word{{ name |title }}
lengthReturn the length of a string or list{{ name |length }}
dateFormat a date{{ date |date:"Y-m-d" }}
defaultProvide a default value if variable is False or empty{{ comment |default:"No comment" }}
truncatewordsTruncate a string to the specified number of words{{ bio |truncatewords:10 }}
safeMark a string as safe, preventing HTML escaping{{ html_content |safe }}

Chaining Filters

You can chain multiple filters together:

html
{{ text|lower|truncatewords:5 }}

This will convert text to lowercase and then truncate it to 5 words.

Template Tags

Template tags provide logic and control flow within templates. They are enclosed in {% %}.

Conditional

html
{% if user.is_authenticated %}
<h1>Welcome, {{ user.username }}!</h1>
{% elif user.is_anonymous %}
<h1>Welcome, Guest!</h1>
{% else %}
<h1>Welcome!</h1>
{% endif %}

Loop

python
# views.py
def my_view(request):
context = {
'fruits': ['apple', 'banana', 'cherry']
}
return render(request, 'my_template.html', context)
html
<!-- my_template.html -->
<ul>
{% for fruit in fruits %}
<li>{{ fruit }}</li>
{% empty %}
<li>No fruits available</li>
{% endfor %}
</ul>

Output:

html
<ul>
<li>apple</li>
<li>banana</li>
<li>cherry</li>
</ul>

The {% empty %} tag is used to display content when the list is empty.

Loop Variables

Inside a for loop, you have access to special variables:

html
<ul>
{% for fruit in fruits %}
<li>{{ forloop.counter }}: {{ fruit }}</li>
{% endfor %}
</ul>

Common loop variables:

  • forloop.counter: The current iteration (1-indexed)
  • forloop.counter0: The current iteration (0-indexed)
  • forloop.first: True if this is the first iteration
  • forloop.last: True if this is the last iteration

URL Tag

The url tag is used to create URLs dynamically:

html
<a href="{% url 'profile' username='john' %}">View Profile</a>

This will generate a URL based on the URL pattern named 'profile' with the parameter username set to 'john'.

Static Tag

The static tag is used to link to static files (CSS, JavaScript, images):

html
{% load static %}
<img src="{% static 'images/logo.png' %}" alt="Logo">
<link rel="stylesheet" href="{% static 'css/style.css' %}">

Comments in Templates

You can add comments that won't be rendered in the final HTML:

html
{# This is a single line comment #}

{% comment %}
This is a multi-line comment.
It can span multiple lines.
{% endcomment %}

Template Inheritance

Template inheritance is one of Django's most powerful features. It allows you to build a base template that contains all the common elements of your site and define blocks that child templates can override.

Base Template

html
<!-- base.html -->
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}My Site{% endblock title %}</title>
<link rel="stylesheet" href="{% static 'css/style.css' %}">
{% block extra_css %}{% endblock extra_css %}
</head>
<body>
<header>
<h1>My Awesome Site</h1>
<nav>
<!-- Navigation menu here -->
</nav>
</header>

<main>
{% block content %}
{% endblock content %}
</main>

<footer>
&copy; 2023 My Site
</footer>

<script src="{% static 'js/main.js' %}"></script>
{% block extra_js %}{% endblock extra_js %}
</body>
</html>

Child Template

html
<!-- home.html -->
{% extends "base.html" %}

{% block title %}Home | My Site{% endblock title %}

{% block content %}
<h2>Welcome to My Site</h2>
<p>This is the home page content.</p>
{% endblock content %}

{% block extra_css %}
<link rel="stylesheet" href="{% static 'css/home.css' %}">
{% endblock extra_css %}

The {% extends %} tag specifies which template to inherit from, and the {% block %} tags define the sections that can be overridden in child templates.

Including Templates

You can include a template within another template using the include tag:

html
<!-- main_template.html -->
<div class="container">
<h1>Main Content</h1>
{% include "sidebar.html" %}
<p>More content here...</p>
</div>

<!-- sidebar.html -->
<div class="sidebar">
<h3>Recent Posts</h3>
<ul>
<li>Post 1</li>
<li>Post 2</li>
</ul>
</div>

Custom Template Tags and Filters

For more advanced functionality, Django allows you to create custom template tags and filters. Let's see a simple example:

  1. Create a directory named templatetags inside your app
  2. Create an __init__.py file inside the templatetags directory
  3. Create a Python module for your custom tags/filters:
python
# myapp/templatetags/custom_filters.py
from django import template

register = template.Library()

@register.filter
def multiply(value, arg):
return value * arg
  1. Use the custom filter in your template:
html
{% load custom_filters %}

<p>{{ product.price|multiply:2 }}</p>

Real-world Example: Blog Post Listing

Let's see a comprehensive example that uses many features of Django Template Language to create a blog post listing page:

python
# views.py
def blog_list(request):
posts = Post.objects.all().order_by('-published_date')
return render(request, 'blog/list.html', {'posts': posts})
html
<!-- blog/list.html -->
{% extends "base.html" %}
{% load static %}

{% block title %}Blog | My Site{% endblock %}

{% block content %}
<div class="blog-list">
<h1>Blog Posts</h1>

{% if posts %}
<div class="post-count">
Showing {{ posts|length }} post{{ posts|length|pluralize }}
</div>

<div class="post-container">
{% for post in posts %}
<article class="post-card {% if forloop.first %}featured{% endif %}">
<header>
<h2>
<a href="{% url 'blog:detail' slug=post.slug %}">
{{ post.title }}
</a>
</h2>
<div class="meta">
Published on {{ post.published_date|date:"F j, Y" }} by {{ post.author.get_full_name|default:post.author.username }}
</div>
</header>

<div class="excerpt">
{{ post.content|truncatewords:30 }}
</div>

<footer>
<div class="tags">
{% for tag in post.tags.all %}
<span class="tag">{{ tag.name }}</span>
{% if not forloop.last %} • {% endif %}
{% empty %}
<span class="no-tags">No tags</span>
{% endfor %}
</div>

<a href="{% url 'blog:detail' slug=post.slug %}" class="read-more">
Read more &raquo;
</a>
</footer>
</article>

{% if not forloop.last %}
<hr class="post-divider">
{% endif %}
{% endfor %}
</div>

{% if is_paginated %}
<div class="pagination">
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}">&laquo; Previous</a>
{% endif %}

{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<span class="current">{{ num }}</span>
{% else %}
<a href="?page={{ num }}">{{ num }}</a>
{% endif %}
{% endfor %}

{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">Next &raquo;</a>
{% endif %}
</div>
{% endif %}

{% else %}
<div class="no-posts">
<p>No blog posts found.</p>
{% if user.is_authenticated and user.is_staff %}
<p>
<a href="{% url 'admin:blog_post_add' %}" class="button">
Create your first post
</a>
</p>
{% endif %}
</div>
{% endif %}
</div>
{% endblock %}

This example demonstrates many key features of DTL:

  • Template inheritance (extends)
  • Loading static files (load static)
  • Conditionals (if, else)
  • Loops (for with empty fallback)
  • Loop variables (forloop.first, forloop.last)
  • URL generation (url tag)
  • Filters (length, pluralize, date, truncatewords, default)
  • Accessing object attributes (e.g., post.title)
  • Nested loops (iterating through post tags)

Summary

Django Template Language is a powerful system that allows you to create dynamic HTML templates with minimal effort. In this guide, we've covered:

  • Using variables with {{ }}
  • Applying filters with the pipe symbol (|)
  • Using template tags with {% %}
  • Conditional logic with if, elif, and else
  • Loops with for
  • Template inheritance with extends and block
  • Including other templates with include
  • Creating custom template tags and filters

DTL is designed to be simple yet flexible, focusing on presentation rather than logic. This separation of concerns helps keep your Django codebase clean, maintainable, and secure.

Exercises

  1. Create a base template for a personal portfolio website with blocks for title, content, and extra CSS/JS.
  2. Create a child template that extends your base template and displays a list of projects with their names, descriptions, and technologies used.
  3. Add a filter to truncate project descriptions to 15 words, and another to display technologies as a comma-separated list.
  4. Create a custom template filter that highlights search terms in project descriptions.
  5. Implement pagination for the projects list.

Additional Resources

With these fundamentals, you're well on your way to creating dynamic and maintainable Django templates for your web applications.



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)