Introduction
Django is a high-level Python web framework that enables rapid development of dynamic web applications. One of its most powerful features is the Django Template Language (DTL), which allows developers to render dynamic content in HTML pages.
DTL is designed to separate presentation from business logic, providing a clean, maintainable approach to creating dynamic websites. It offers template syntax, variables, filters, and tags that help developers render database content, perform conditional operations, and iterate over data structures in a straightforward way.
This guide will cover the basics of DTL, including template syntax, variables, filters, and basic tags, so that you can create dynamic HTML pages using Django efficiently.
1. What is Django Template Language
The Django Template Language (DTL) is a text-based system for generating dynamic HTML pages. It is designed to:
- Keep the HTML separate from Python code.
- Allow developers to pass variables and data from views.
- Use filters and tags to format and manipulate data.
- Include control structures like loops and conditionals.
Templates are rendered by Django when a view function calls render()
, combining the HTML structure with context data provided by the view.
2. Setting Up Templates in Django
Before using DTL, you need to configure templates:
- Create a folder named
templates
in your Django app:
myapp/
templates/
myapp/
index.html
- Configure
settings.py
to tell Django where to look for templates:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
APP_DIRS: True
ensures Django searches in each app’s templates
folder.
3. Template Syntax
DTL has a simple syntax:
- Variables: Denoted by double curly braces
{{ variable }}
. - Tags: Denoted by
{% tag %}
; used for logic and control structures. - Comments:
{# comment #}
; ignored in the rendered HTML.
Example:
<h1>{{ title }}</h1>
<p>{% if user %}Welcome, {{ user.username }}{% else %}Hello, Guest{% endif %}</p>
This template displays the title
variable and a conditional greeting.
4. Passing Variables from Views
Variables are sent to templates via the context dictionary in a view.
from django.shortcuts import render
def home(request):
context = {
'title': 'Welcome to My Site',
'user': request.user
}
return render(request, 'myapp/index.html', context)
In the template, you access these variables with {{ title }}
and {{ user }}
.
5. Using Filters
Filters allow you to modify variables before rendering. They are applied with the |
symbol.
Common Filters:
upper
: Converts text to uppercase.lower
: Converts text to lowercase.title
: Capitalizes each word.length
: Returns length of a string or list.default
: Provides a fallback if a variable is empty.date
: Formats date objects.
Example:
<p>{{ title|upper }}</p>
<p>Number of items: {{ items|length }}</p>
<p>{{ username|default:"Guest" }}</p>
<p>Date: {{ today|date:"F d, Y" }}</p>
Filters can be chained:
<p>{{ username|lower|title }}</p>
6. Using Basic Template Tags
Template tags control logic in templates. Common tags include:
- If Tag: Conditional statements.
{% if user.is_authenticated %}
<p>Welcome back, {{ user.username }}</p>
{% else %}
<p>Hello, Guest!</p>
{% endif %}
- For Tag: Loops over lists or querysets.
<ul>
{% for item in items %}
<li>{{ item.name }}</li>
{% endfor %}
</ul>
- Empty Clause in Loops:
<ul>
{% for item in items %}
<li>{{ item.name }}</li>
{% empty %}
<li>No items available.</li>
{% endfor %}
</ul>
- Comment Tag:
{# This is a comment and will not appear in the HTML #}
7. Using Variables in Templates
Variables can be:
- Strings:
{{ name }}
- Numbers:
{{ age }}
- Lists:
{{ items }}
- Dictionaries:
{{ person.name }}
Nested variables use dot notation:
<p>Author: {{ book.author.name }}</p>
DTL automatically escapes HTML to prevent XSS attacks. For safe HTML, use safe
filter:
{{ content|safe }}
8. Template Inheritance
DTL supports template inheritance, which reduces redundancy:
- Base Template (
base.html
):
<html>
<head>
<title>{% block title %}My Website{% endblock %}</title>
</head>
<body>
<header>
<h1>Site Header</h1>
</header>
{% block content %}{% endblock %}
<footer>
<p>&copy; 2025 My Website</p>
</footer>
</body>
</html>
- Child Template (
home.html
):
{% extends 'base.html' %}
{% block title %}Home{% endblock %}
{% block content %}
<h2>Welcome to the Home Page</h2>
{% endblock %}
Blocks allow child templates to override portions of the base template.
9. Including Templates
You can include reusable components using {% include %}
:
{% include 'myapp/navbar.html' %}
This is ideal for headers, footers, or menus.
10. Using with
Tag
The with
tag allows you to define a variable for use in a block:
{% with total=items|length %}
<p>Total items: {{ total }}</p>
{% endwith %}
11. Template Filters: Advanced Examples
truncatechars
: Truncates text to a specific number of characters.
<p>{{ article.content|truncatechars:50 }}</p>
date
andtime
formatting:
<p>Published: {{ article.date|date:"D, M d Y" }}</p>
default_if_none
: Uses fallback if value is None.
<p>{{ user.bio|default_if_none:"No bio provided" }}</p>
join
: Converts list to a string.
<p>Tags: {{ tags|join:", " }}</p>
pluralize
: Adds plural endings conditionally.
<p>{{ items|length }} item{{ items|length|pluralize }}</p>
12. Loop Variables
Inside loops, Django provides special variables:
forloop.counter
: 1-based index.forloop.counter0
: 0-based index.forloop.first
: True if first iteration.forloop.last
: True if last iteration.forloop.parentloop
: Access outer loop in nested loops.
Example:
<ul>
{% for item in items %}
<li>{{ forloop.counter }}. {{ item.name }}{% if forloop.last %} (Last Item){% endif %}</li>
{% endfor %}
</ul>
13. Using ifchanged
ifchanged
displays content only if it changes between loop iterations.
{% for item in items %}
{% ifchanged item.category %}
<h2>{{ item.category }}</h2>
{% endifchanged %}
<p>{{ item.name }}</p>
{% endfor %}
14. Escaping and Safe Output
DTL escapes HTML by default:
{{ user_input }}
This prevents scripts from executing. To render raw HTML:
{{ trusted_html|safe }}
Use carefully to avoid security risks.
15. Using firstof
The firstof
tag displays the first non-empty variable:
<p>{{ user.nickname|firstof:user.username|default:"Guest" }}</p>
16. Using cycle
in Loops
cycle
helps alternate styles:
{% for item in items %}
<tr class="{% cycle 'odd' 'even' %}">
<td>{{ item.name }}</td>
</tr>
{% endfor %}
17. Using url
Tag
The url
tag generates URLs dynamically:
<a href="{% url 'book-detail' book.id %}">{{ book.title }}</a>
It references the view name in urls.py
, avoiding hardcoding URLs.
18. Static Files in Templates
Use {% load static %}
to include CSS, JS, or images:
{% load static %}
<link rel="stylesheet" href="{% static 'myapp/style.css' %}">
<img src="{% static 'myapp/logo.png' %}" alt="Logo">
19. Using csrf_token
in Forms
For forms, always include CSRF token:
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
Django protects against CSRF attacks with this token.
20. Context Processors
Context processors provide global template variables. Examples:
request
: Access request object.user
: Current authenticated user.messages
: Django messages framework.
You can also create custom context processors to add global data like site name or current year.
21. Custom Template Filters
You can define custom filters in templatetags
:
# myapp/templatetags/custom_filters.py
from django import template
register = template.Library()
@register.filter
def multiply(value, arg):
return value * arg
Use in template:
{% load custom_filters %}
<p>{{ price|multiply:3 }}</p>
22. Custom Template Tags
Custom tags can perform logic or render content:
# myapp/templatetags/custom_tags.py
from django import template
register = template.Library()
@register.simple_tag
def greeting(name):
return f"Hello, {name}!"
Usage:
{% load custom_tags %}
<p>{% greeting "Alice" %}</p>
23. Using include
with Context
You can pass additional context when including a template:
{% include 'myapp/navbar.html' with user=user show_menu=True %}
24. Template Debugging
To debug templates:
- Use
{% debug %}
to display current context. - Ensure variables exist in the context dictionary.
- Check spelling and case-sensitivity in variable names.
- Use
default
filter to avoid empty values.
25. Best Practices for DTL
- Keep logic in views, not templates.
- Use template inheritance for reusable layout.
- Use filters instead of Python logic in templates.
- Organize templates by app.
- Avoid hardcoding URLs; use
{% url %}
. - Escape user input unless trusted.
- Use context processors for global data.
- Keep templates readable and maintainable.
26. Example: Dynamic Page
View (views.py
):
from django.shortcuts import render
def product_list(request):
products = [
{'name': 'Laptop', 'price': 1200},
{'name': 'Phone', 'price': 800},
{'name': 'Tablet', 'price': 400},
]
context = {'products': products, 'title': 'Our Products'}
return render(request, 'myapp/products.html', context)
Template (products.html
):
{% extends 'base.html' %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<h1>{{ title }}</h1>
<ul>
{% for product in products %}
<li>{{ product.name }} - ${{ product.price }}</li>
{% empty %}
<li>No products available.</li>
{% endfor %}
</ul>
{% endblock %}
This dynamically renders a list of products.
Leave a Reply