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
# views.py
def my_view(request):
return render(request, 'my_template.html', {'name': 'John', 'age': 25})
<!-- my_template.html -->
<h1>Hello, {{ name }}!</h1>
<p>You are {{ age }} years old.</p>
Output:
<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:
# views.py
def my_view(request):
context = {
'person': {
'name': 'John',
'age': 25
},
'fruits': ['apple', 'banana', 'cherry']
}
return render(request, 'my_template.html', context)
<!-- my_template.html -->
<p>Name: {{ person.name }}</p>
<p>Age: {{ person.age }}</p>
<p>First fruit: {{ fruits.0 }}</p>
Output:
<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 (|
).
<!-- 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:
Filter | Description | Example |
---|---|---|
lower | Convert to lowercase | {{ name |lower }} |
upper | Convert to uppercase | {{ name |upper }} |
title | Capitalize first letter of each word | {{ name |title }} |
length | Return the length of a string or list | {{ name |length }} |
date | Format a date | {{ date |date:"Y-m-d" }} |
default | Provide a default value if variable is False or empty | {{ comment |default:"No comment" }} |
truncatewords | Truncate a string to the specified number of words | {{ bio |truncatewords:10 }} |
safe | Mark a string as safe, preventing HTML escaping | {{ html_content |safe }} |
Chaining Filters
You can chain multiple filters together:
{{ 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
{% if user.is_authenticated %}
<h1>Welcome, {{ user.username }}!</h1>
{% elif user.is_anonymous %}
<h1>Welcome, Guest!</h1>
{% else %}
<h1>Welcome!</h1>
{% endif %}
Loop
# views.py
def my_view(request):
context = {
'fruits': ['apple', 'banana', 'cherry']
}
return render(request, 'my_template.html', context)
<!-- my_template.html -->
<ul>
{% for fruit in fruits %}
<li>{{ fruit }}</li>
{% empty %}
<li>No fruits available</li>
{% endfor %}
</ul>
Output:
<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:
<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 iterationforloop.last
: True if this is the last iteration
URL Tag
The url
tag is used to create URLs dynamically:
<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):
{% 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:
{# 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
<!-- 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>
© 2023 My Site
</footer>
<script src="{% static 'js/main.js' %}"></script>
{% block extra_js %}{% endblock extra_js %}
</body>
</html>
Child Template
<!-- 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:
<!-- 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:
- Create a directory named
templatetags
inside your app - Create an
__init__.py
file inside thetemplatetags
directory - Create a Python module for your custom tags/filters:
# myapp/templatetags/custom_filters.py
from django import template
register = template.Library()
@register.filter
def multiply(value, arg):
return value * arg
- Use the custom filter in your template:
{% 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:
# views.py
def blog_list(request):
posts = Post.objects.all().order_by('-published_date')
return render(request, 'blog/list.html', {'posts': posts})
<!-- 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 »
</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 }}">« 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 »</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
withempty
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
, andelse
- Loops with
for
- Template inheritance with
extends
andblock
- 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
- Create a base template for a personal portfolio website with blocks for title, content, and extra CSS/JS.
- Create a child template that extends your base template and displays a list of projects with their names, descriptions, and technologies used.
- Add a filter to truncate project descriptions to 15 words, and another to display technologies as a comma-separated list.
- Create a custom template filter that highlights search terms in project descriptions.
- Implement pagination for the projects list.
Additional Resources
- Django Template Language Documentation
- Built-in Template Tags and Filters
- Custom Template Tags and Filters
- Template Inheritance
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! :)