Django Template Language

The Django Template Language (DTL) is a powerful and flexible tool for rendering dynamic HTML pages in Django applications. It allows you to separate the design of your pages from the Python code, promoting a clean and maintainable codebase.

Basic Syntax

Django templates use the following basic syntax elements:

  1. Variables: Enclosed in double curly braces {{ }}.
  2. Tags: Enclosed in {% %}.
  3. Filters: Applied to variables using the pipe symbol |.
  4. Comments: Enclosed in {# #} for single-line or {% comment %} and {% endcomment %} for multi-line.

Variables

Variables in templates are rendered by the context dictionary passed from the view:

<h1>Hello, {{ name }}!</h1>

You can access attributes of objects using dot notation:

<p>The first item in the list is {{ my_list.0 }}</p>
<p>The user's username is {{ user.username }}</p>

Tags

Tags provide logic and control flow in templates:

{% if user.is_authenticated %}
    <p>Welcome, {{ user.username }}!</p>
{% else %}
    <p>Please log in.</p>
{% endif %}

{% for item in item_list %}
    <li>{{ item }}</li>
{% empty %}
    <li>No items in the list.</li>
{% endfor %}

Filters

Filters modify the output of variables:

<p>The product costs {{ price|floatformat:2 }}</p>
<p>{{ my_date|date:"Y-m-d" }}</p>
<p>{{ my_text|upper|truncatewords:30 }}</p>

Built-in Tags and Filters

Django provides numerous built-in tags and filters. Here are some commonly used ones:

Tags

  • {% if %}, {% elif %}, {% else %}: Conditional statements
  • {% for %}: Looping
  • {% url %}: URL reversing
  • {% block %}, {% extends %}: Template inheritance
  • {% include %}: Including other templates
  • {% csrf_token %}: Cross-Site Request Forgery protection

Filters

  • date: Formats a date
  • default: Sets a default value if the variable is False or empty
  • length: Returns the length of a list
  • lower, upper: Changes case
  • safe: Marks a string as safe, preventing auto-escaping

Custom Tags and Filters

You can create custom template tags and filters to extend DTL's functionality:

# In your_app/templatetags/custom_tags.py
from django import template

register = template.Library()

@register.filter
def multiply(value, arg):
    return value * arg

@register.simple_tag
def current_time(format_string):
    from django.utils import timezone
    return timezone.now().strftime(format_string)

To use custom tags, load them in your template:

{% load custom_tags %}

<p>{{ 5|multiply:3 }}</p>
<p>The current time is {% current_time "%Y-%m-%d %I:%M %p" %}</p>

Template Inheritance

Template inheritance is a powerful feature that allows you to build a base "skeleton" template that contains all the common elements of your site and defines blocks that child templates can override.

Base template (base.html):

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}My Site{% endblock %}</title>
</head>
<body>
    <div id="sidebar">
        {% block sidebar %}
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/blog/">Blog</a></li>
        </ul>
        {% endblock %}
    </div>

    <div id="content">
        {% block content %}{% endblock %}
    </div>
</body>
</html>

Child template:

{% extends "base.html" %}

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

{% block content %}
    <h1>My Blog</h1>
    {% for entry in blog_entries %}
        <h2>{{ entry.title }}</h2>
        <p>{{ entry.body }}</p>
    {% endfor %}
{% endblock %}

Context Processors

Context processors let you add variables to the context for all templates:

# In your settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        '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',
                'your_app.context_processors.your_custom_processor',
            ],
        },
    },
]

# In your_app/context_processors.py
def your_custom_processor(request):
    return {
        'site_name': 'My Awesome Site',
        'current_year': datetime.now().year,
    }

Best Practices

  1. Keep logic in views: Templates should focus on presentation. Complex logic belongs in views or model methods.
  2. Use template inheritance: Leverage {% extends %} and {% block %} to create a consistent layout across your site.
  3. Minimize database queries: Use select_related() and prefetch_related() in your views to reduce database hits.
  4. Use the with tag: For complex computations that are used multiple times in a template.
  5. Be cautious with {% autoescape off %}: Only use when absolutely necessary to prevent XSS vulnerabilities.

Conclusion

The Django Template Language is a versatile tool that allows for clean separation of logic and presentation in your Django applications. By mastering its syntax, built-in tags and filters, and advanced features like custom tags and template inheritance, you can create dynamic, efficient, and maintainable templates for your web applications.