Skip to content

Django - 模板系统

Django 的模板系统提供了一种强大且对设计师友好的方式,将文档的呈现(HTML)与其数据(Python 逻辑)分离。它使用一种迷你语言,即 Django 模板语言(Django Template Language, DTL),将逻辑和变量嵌入到 HTML 文件中。

如同在视图章节中所见,django.shortcuts.render 函数常用于将模板与上下文字典(context dictionary)结合,并返回一个 HttpResponse 对象。

from django.shortcuts import render
import datetime
def current_datetime(request):
now = datetime.datetime.now()
context = {'current_date': now}
return render(request, 'myapp/datetime.html', context)

这个函数通常接受三个参数:

  • request:HttpRequest 对象。
  • template_name:模板文件的路径(相对于 settings.py 中 TEMPLATES 设置指定的目录,通常在应用的 templates 子目录内)。
  • context:一个字典,将变量名(键)映射到它们的值。这些变量在模板中变得可访问。

DTL 定义了在模板文件中使用变量、标签、过滤器和注释的语法。

变量被双花括号包裹:{{ variable }}。当模板引擎遇到变量时,它会使用提供的上下文(context)对其进行求值,并将变量标签替换为结果。

示例:使用上述视图提供的上下文的 myapp/templates/myapp/datetime.html 文件内容:

myapp/templates/myapp/datetime.html
<!-- myapp/templates/myapp/datetime.html -->
<!DOCTYPE html>
<html>
<head><title>Current Time</title></head>
<head><title>当前时间</title></head>
<body>
<p>The current date and time is: {{ current_date }}</p>
<p>当前日期和时间是:{{ current_date }}</p>
</body>
</html>

输出可能看起来像:当前日期和时间是:2023 年 9 月 11 日 下午 4:01(Django 会自动格式化 datetime 对象)。

点号查找: 你可以使用点号(.)符号访问变量的属性,类似于 Python。Django 会按字典查找、属性查找和列表索引查找的顺序尝试。

示例:如果 current_date 是一个 datetime 对象,{{ current_date.year }} 将输出年份。

过滤器(Filter)({{ variable|filter }})

Section titled “过滤器(Filter)({{ variable|filter }})”

过滤器用于修改变量的显示方式。它们通过管道符(|)应用。

常见示例:

  • {{ user_bio|truncatewords:30 }}:将字符串截断到前 30 个词。
  • {{ page_title|lower }}:将字符串转换为小写。
  • {{ item_list|length }}:返回列表的长度。
  • {{ article.publication_date|date:“Y-m-d” }}:格式化日期对象(使用 PHP 日期格式说明符)。
  • {{ raw_html|safe }}:将字符串标记为安全,防止自动转义(请谨慎使用!)。
  • {{ value|default:“N/A” }}:如果 value 为 False 或为空,则提供默认值。

过滤器可以链式使用:{{ my_text|escape|linebreaks }}。

查找更多内置过滤器:Django 内置过滤器参考

标签在模板中提供了逻辑,例如循环、条件判断、模板继承、加载外部资源等。它们被 {% 和 %} 包围。

{% if %}、{% elif %}、{% else %}、{% endif %}

Section titled “{% if %}、{% elif %}、{% else %}、{% endif %}”

执行条件逻辑。

{% if user.is_authenticated %}
<p>Welcome, {{ user.username }}!</p>
<p>欢迎, {{ user.username }}!</p>
{% elif user.is_guest %}
<p>Welcome, Guest!</p>
<p>欢迎, 访客!</p>
{% else %}
<p><a href="{% url 'login' %}">Log in</a></p>
<p><a href="{% url 'login' %}">登录</a></p>
{% endif %}

循环遍历序列(如列表或查询集 queryset)中的项目。可选的 {% empty %} 块在序列为空时渲染。

<ul>
{% for item in item_list %}
<li>{{ forloop.counter }}: {{ item.name }}</li>
{% empty %}
<li>No items available.</li>
<li>没有可用项目。</li>
{% endfor %}
</ul>

forloop 变量提供了关于循环状态的信息(例如 forloop.counter、forloop.first、forloop.last)。

{% extends %} 和 {% block %}(模板继承)

Section titled “{% extends %} 和 {% block %}(模板继承)”

这个强大的特性允许你创建一个包含网站通用元素的基础模板骨架,以及可以覆盖特定部分的子模板。

基础模板(myapp/templates/myapp/base.html):

myapp/templates/myapp/base.html
<!-- myapp/templates/myapp/base.html -->
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}My Site{% endblock %}</title>
<title>{% block title %}我的网站{% endblock %}</title>
<!-- Common CSS/JS -->
<!-- 通用 CSS/JS -->
</head>
<body>
<header>Site Header</header>
<header>网站头部</header>
<main>
{% block content %}
<!-- Default content goes here -->
<!-- 默认内容放在这里 -->
{% endblock %}
</main>
<footer>Site Footer</footer>
<footer>网站底部</footer>
</body>
</html>

子模板(myapp/templates/myapp/specific_page.html):

myapp/templates/myapp/specific_page.html
<!-- myapp/templates/myapp/specific_page.html -->
{% extends "myapp/base.html" %}
{% block title %}Specific Page Title{% endblock %}
{% block title %}特定页面标题{% endblock %}
{% block content %}
<h2>Welcome to the Specific Page</h2>
<h2>欢迎来到特定页面</h2>
<p>This content overrides the base template's content block.</p>
<p>此内容覆盖了基础模板的内容块。</p>
{% endblock %}

{% extends %} 标签必须是子模板中的第一个标签。它指定了父模板。{% block %} 标签定义了子模板可以覆盖的区域。

根据你的 urls.py 中定义的名称生成 URL。这避免了硬编码 URL,使你的应用程序更易于维护。

<a href="{% url 'article-detail' article.id %}">Read More</a>
<a href="{% url 'article-detail' article.id %}">阅读更多</a>
<form action="{% url 'search' %}" method="get">
</form>

加载自定义模板标签和过滤器。

{% load static %}
{% load humanize %}
<img src="{% static 'images/logo.png' %}" alt="Logo">
<img src="{% static 'images/logo.png' %}" alt="Logo">
<p>Value: {{ large_number|intcomma }}</p>
<p>值: {{ large_number|intcomma }}</p>

{% static %}(需要 {% load static %})

Section titled “{% static %}(需要 {% load static %})”

根据你的 STATIC_URL 设置生成静态文件(CSS、JavaScript、图片)的 URL。

单行注释:{# 这是模板注释 #} 多行注释:{% comment %} … 注释内容 … {% endcomment %} 这些注释不会包含在最终的 HTML 输出中。

进一步阅读:Django 模板语言文档