Django Template Language (DTL) Basics

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:

  1. Create a folder named templates in your Django app:
myapp/
templates/
    myapp/
        index.html
  1. 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:

  1. Variables: Denoted by double curly braces {{ variable }}.
  2. Tags: Denoted by {% tag %}; used for logic and control structures.
  3. 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:

  1. If Tag: Conditional statements.
{% if user.is_authenticated %}
&lt;p&gt;Welcome back, {{ user.username }}&lt;/p&gt;
{% else %}
&lt;p&gt;Hello, Guest!&lt;/p&gt;
{% endif %}
  1. For Tag: Loops over lists or querysets.
<ul>
{% for item in items %}
&lt;li&gt;{{ item.name }}&lt;/li&gt;
{% endfor %} </ul>
  1. Empty Clause in Loops:
<ul>
{% for item in items %}
&lt;li&gt;{{ item.name }}&lt;/li&gt;
{% empty %}
&lt;li&gt;No items available.&lt;/li&gt;
{% endfor %} </ul>
  1. 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:

  1. Base Template (base.html):
<html>
<head>
&lt;title&gt;{% block title %}My Website{% endblock %}&lt;/title&gt;
</head> <body>
&lt;header&gt;
    &lt;h1&gt;Site Header&lt;/h1&gt;
&lt;/header&gt;
{% block content %}{% endblock %}
&lt;footer&gt;
    &lt;p&gt;&amp;copy; 2025 My Website&lt;/p&gt;
&lt;/footer&gt;
</body> </html>
  1. Child Template (home.html):
{% extends 'base.html' %}

{% block title %}Home{% endblock %}

{% block content %}
&lt;h2&gt;Welcome to the Home Page&lt;/h2&gt;
{% 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 and time 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 %}
&lt;li&gt;{{ forloop.counter }}. {{ item.name }}{% if forloop.last %} (Last Item){% endif %}&lt;/li&gt;
{% endfor %} </ul>

13. Using ifchanged

ifchanged displays content only if it changes between loop iterations.

{% for item in items %}
{% ifchanged item.category %}
    &lt;h2&gt;{{ item.category }}&lt;/h2&gt;
{% endifchanged %}
&lt;p&gt;{{ item.name }}&lt;/p&gt;
{% 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 %}
&lt;tr class="{% cycle 'odd' 'even' %}"&gt;
    &lt;td&gt;{{ item.name }}&lt;/td&gt;
&lt;/tr&gt;
{% 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 }}
&lt;button type="submit"&gt;Submit&lt;/button&gt;
</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:

  1. Use {% debug %} to display current context.
  2. Ensure variables exist in the context dictionary.
  3. Check spelling and case-sensitivity in variable names.
  4. Use default filter to avoid empty values.

25. Best Practices for DTL

  1. Keep logic in views, not templates.
  2. Use template inheritance for reusable layout.
  3. Use filters instead of Python logic in templates.
  4. Organize templates by app.
  5. Avoid hardcoding URLs; use {% url %}.
  6. Escape user input unless trusted.
  7. Use context processors for global data.
  8. Keep templates readable and maintainable.

26. Example: Dynamic Page

View (views.py):

from django.shortcuts import render

def product_list(request):
products = &#91;
    {'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 %}
&lt;li&gt;{{ product.name }} - ${{ product.price }}&lt;/li&gt;
{% empty %}
&lt;li&gt;No products available.&lt;/li&gt;
{% endfor %} </ul> {% endblock %}

This dynamically renders a list of products.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *