Detailed explanation of django Template template layer

As a powerful web framework, django's template system is an integral part of building dynamic web pages. Today, we will delve into the working principles, grammatical features, and advanced usage of the Django template system to help you quickly master this core skill.

Course Objectives

  • Understand how the Django template system works
  • Master template syntax and use of tags
  • Learn to create and use custom template tags and filters
  • Understand template inheritance and inclusion mechanisms

Template system overview

The django template system is the "T" layer (Template) in the django MTV architecture, which is responsible for rendering data into output in HTML or other formats. The template system provides a concise yet powerful syntax that allows designers and developers to collaborate on building dynamic web pages.

Composition of template system:

  • Template: text file containing placeholders and labels
  • Context: the data passed to the template
  • Rendering: The process of populating context data into the template

Basic template syntax

Variables

Template variables are used to display data passed from the view. Variable names consist of letters, numbers, underscores, and dots, surrounded by double curly braces.

<!-- 在模板中显示变量 -->
<p>欢迎,{{ name }}!</p>
<p>今天的日期是 {{ date }}</p>

<!-- 访问对象属性 -->
<p>用户名:{{ user.username }}</p>
<p>邮箱:{{ user.email }}</p>

<!-- 访问字典值 -->
<p>城市:{{ profile.address.city }}</p>

Filter

Filters are used to modify the display format of variables, using the pipe character|To apply filters, multiple filters can be called in a chain.

<!-- 过滤器用于格式化变量 -->
<p>{{ name|upper }}</p>  <!-- 转为大写 -->
<p>{{ content|truncatewords:30 }}</p>  <!-- 截断为30个单词 -->
<p>{{ price|floatformat:2 }}</p>  <!-- 保留两位小数 -->
<p>{{ date|date:"Y-m-d H:i:s" }}</p>  <!-- 格式化日期 -->

<!-- 链式过滤器 -->
<p>{{ content|striptags|truncatewords:50 }}</p>

Template tag

The template tag consists of{%and%}Surrounding is used to perform logical operations, such as loops, conditional judgments, etc.

Control structure tag

if/elif/else tag

Conditional tags allow you to display different content based on conditions.

{% if user.is_authenticated %}
    <p>欢迎回来,{{ user.username }}!</p>
{% elif user.is_anonymous %}
    <p>请登录</p>
{% else %}
    <p>未知用户</p>
{% endif %}

<!-- 使用比较运算符 -->
{% if articles|length > 5 %}
    <p>文章数量较多</p>
{% endif %}

for loop label

The for tag is used to iterate over a sequence and also provides a series of useful loop variables.

<!-- 基本for循环 -->
<ul>
{% for article in articles %}
    <li>{{ article.title }}</li>
{% empty %}
    <li>暂无文章</li>
{% endfor %}
</ul>

<!-- 带索引的循环 -->
{% for article in articles %}
    <p>{{ forloop.counter }}. {{ article.title }}</p>
{% endfor %}

Commonly used forloop variables:

  • forloop.counter: Counter starting from 1
  • forloop.counter0: Counter starting from 0
  • forloop.revcounter: reverse counter
  • forloop.first: Whether it is the first element
  • forloop.last: Whether it is the last element

Template inheritance

Template inheritance is one of the most powerful parts of Django's template system, allowing you to create a base "skeleton" template that contains all the common elements of your site and define blocks that child templates can override.

<!-- base.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}默认标题{% endblock %}</title>
    {% block extra_head %}{% endblock %}
</head>
<body>
    <header>
        {% block header %}
            <h1>我的网站</h1>
        {% endblock %}
    </header>
    
    <main>
        {% block content %}{% endblock %}
    </main>
    
    <footer>
        {% block footer %}
            <p>&copy; 2023 版权所有</p>
        {% endblock %}
    </footer>
    
    {% block extra_js %}{% endblock %}
</body>
</html>
<!-- article_list.html -->
{% extends "base.html" %}

{% block title %}文章列表 - 我的博客{% endblock %}

{% block content %}
    <h2>文章列表</h2>
    {% for article in articles %}
        <article>
            <h3><a href="{% url 'article_detail' article.id %}">{{ article.title }}</a></h3>
            <p>{{ article.summary|truncatewords:30 }}</p>
            <p class="meta">发布于 {{ article.pub_date|date:"Y-m-d" }}</p>
        </article>
    {% empty %}
        <p>暂无文章</p>
    {% endfor %}
    
    <!-- 分页 -->
    {% if articles.has_other_pages %}
        <div class="pagination">
            {% if articles.has_previous %}
                <a href="?page={{ articles.previous_page_number }}">上一页</a>
            {% endif %}
            
            <span class="current">
                第 {{ articles.number }} 页,共 {{ articles.paginator.num_pages }} 页
            </span>
            
            {% if articles.has_next %}
                <a href="?page={{ articles.next_page_number }}">下一页</a>
            {% endif %}
        </div>
    {% endif %}
{% endblock %}

URL tags and reverse

url tag

The url tag allows you to reference named URL configurations instead of hard-coded URLs.

<!-- 使用命名URL -->
<a href="{% url 'article_detail' article.id %}">查看详情</a>

<!-- 带参数的URL -->
<a href="{% url 'articles_by_category' category.slug %}">{{ category.name }}</a>

<!-- 带多个参数的URL -->
<a href="{% url 'article_edit' article.id user.id %}">编辑</a>

<!-- 使用命名参数 -->
<a href="{% url 'search' q=query page=1 %}">搜索</a>

static tag

The static tag is used to reference static files such as CSS, JavaScript, and images.

{% load static %}
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">
    <link rel="icon" href="{% static 'images/favicon.ico' %}">
</head>
<body>
    <img src="{% static 'images/logo.png' %}" alt="Logo">
    <script src="{% static 'js/main.js' %}"></script>
</body>
</html>

Commonly used template tags

include tag

The include tag allows you to include other templates within a template, which is useful for reusing page components.

<!-- 包含其他模板 -->
{% include 'partials/header.html' %}
{% include 'partials/sidebar.html' %}

<!-- 带上下文的包含 -->
{% include 'partials/comment_form.html' with comment=article.comment %}

<!-- 有条件地包含 -->
{% include 'partials/ad_banner.html' ignore missing %}

with tag

The with tag allows you to create temporary variables in the template, which is especially useful for complex expressions.

<!-- 创建临时变量 -->
{% with total=article.views|add:article.likes %}
    <p>互动总数:{{ total }}</p>
{% endwith %}

<!-- 复杂表达式 -->
{% with user.profile as profile %}
    <p>昵称:{{ profile.nickname }}</p>
    <p>积分:{{ profile.points }}</p>
{% endwith %}

cycle tag

The cycle tag is used to rotate a series of values ​​in a loop. A common use is to alternately set colors for table rows.

<!-- 循环使用值 -->
{% for item in items %}
    <tr class="{% cycle 'row1' 'row2' %}">
        <td>{{ item.name }}</td>
        <td>{{ item.value }}</td>
    </tr>
{% endfor %}

Custom template filter

When the built-in filters don't meet your needs, you can create custom filters.

Create a custom filter

# templatetags/custom_filters.py
from django import template
from django.utils.safestring import mark_safe
import markdown

register = template.Library()

@register.filter
def markdown_to_html(text):
    """将Markdown转换为HTML"""
    return mark_safe(markdown.markdown(text))

@register.filter
def pluralize_cn(count, singular, plural):
    """中文复数形式"""
    if count == 1:
        return singular
    else:
        return plural

@register.filter
def truncatechars_middle(text, length):
    """从中间截断文本"""
    if len(text) <= length:
        return text
    else:
        start = length // 2
        end = length - start - 3
        return text[:start] + "..." + text[-end:]

Use custom filters in templates

{% load custom_filters %}

<!-- 使用自定义过滤器 -->
<div class="content">
    {{ article.content|markdown_to_html }}
</div>

<p>有 {{ comments.count }} {{ comments.count|pluralize_cn:"条评论":"条评论" }}</p>

<p>{{ long_text|truncatechars_middle:50 }}</p>

Custom template tags

In addition to filters, you can create custom tags to perform more complex actions.

Simple tags

Simple tags accept parameters and return a string.

# templatetags/custom_tags.py
from django import template
from django.utils import timezone
from myapp.models import Article

register = template.Library()

@register.simple_tag
def current_time(format_string):
    """显示当前时间"""
    return timezone.now().strftime(format_string)

@register.simple_tag
def get_recent_articles(count=5):
    """获取最新文章"""
    return Article.objects.filter(
        is_published=True
    ).order_by('-pub_date')[:count]

@register.simple_tag(takes_context=True)
def get_user_articles(context, user):
    """获取用户的文章"""
    request = context['request']
    return user.article_set.filter(author=request.user)

Contains tags

The include tag renders another template, similar to the include tag, but can contain more logic.

@register.inclusion_tag('tags/article_list.html')
def show_articles(articles, show_author=True):
    """显示文章列表"""
    return {
        'articles': articles,
        'show_author': show_author
    }

@register.inclusion_tag('tags/pagination.html', takes_context=True)
def show_pagination(context, page_obj):
    """显示分页"""
    request = context['request']
    return {
        'page_obj': page_obj,
        'request': request
    }

Use custom tags in templates

{% load custom_tags %}

<!-- 使用简单标签 -->
<p>当前时间:{% current_time "%Y-%m-%d %H:%M:%S" %}</p>

<!-- 获取最新文章 -->
{% get_recent_articles 3 as recent_articles %}
<ul>
{% for article in recent_articles %}
    <li><a href="{{ article.get_absolute_url }}">{{ article.title }}</a></li>
{% endfor %}
</ul>

Template configuration

In Django's settings.py, you can configure the behavior of the template engine.

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.djangoTemplates',
        'DIRS': [
            BASE_DIR / 'templates',  # 模板目录
        ],
        'APP_DIRS': True,  # 自动查找应用中的templates目录
        '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',
            ],
        },
    },
]

Template Best Practices

Template organization principles

  • Use template inheritance to reduce duplicate code
  • Extract common parts into independent templates
  • Proper use of include tags
  • Avoid placing complex logic in templates

Performance optimization

<!-- 使用select_related和prefetch_related优化查询 -->
{% for article in articles.all %}
    <!-- 如果需要访问外键对象 -->
    <p>作者:{{ article.author.username }}</p>
{% endfor %}
# 在视图中优化查询
def article_list(request):
    articles = Article.objects.select_related('author').prefetch_related('tags')
    return render(request, 'articles/list.html', {'articles': articles})

Security considerations

  • The Django template system HTML-escapes output by default
  • usesafeBe cautious when filtering
  • Avoid performing dangerous operations in templates
<!-- 安全的输出 -->
<p>{{ user_input|escape }}</p>

<!-- 只有在信任内容时才使用safe -->
<div>{{ trusted_html|safe }}</div>

Course Summary

In this lesson, we have an in-depth study of Django's template system, including template syntax, tag usage, template inheritance, custom filters and tags, etc. The template system is an important part of Django, and mastering it is crucial to building dynamic web pages.

Through the proper use of template inheritance, custom tags, and filters, you can create templates with a clear structure and easy maintenance while maintaining the DRY principle of your code. In actual development, remember to follow best practices and pay attention to performance optimization and security considerations, which will help you build more efficient and secure web applications.