云计算百科
云计算领域专业知识百科平台

Django入门教程(五):模板系统详解——变量、标签、过滤器与模板继承

一、为什么需要模板系统?

在第二篇中,我们曾用 HttpResponse 直接返回字符串:

from django.http import HttpResponse

def hello(request):
return HttpResponse("Hello, Django!")

这种方式虽然简单,但把 HTML 内容硬编码在 Python 代码里,存在明显问题:

  • 数据与视图混合:违反 Django 的 MVT 设计思想。

  • 无法复用:页面头部、尾部等公共结构需要反复编写。

  • 难以维护:前端改动需要修改 Python 代码。

Django 的模板系统(Template System)正是为了解决这些问题而设计的。它允许你把 HTML 结构与 Python 数据分离,通过简单的标签和变量动态生成页面。

核心能力一览:

功能语法/示例适用场景
变量渲染 {{ variable }} 动态显示数据
逻辑控制 {% if %}、{% for %} 条件/循环渲染
模板继承 {% extends %}、{% block %} 避免重复 HTML 结构
静态文件 {% static 'path' %} 加载 CSS/JS/图片
自定义过滤器 @register.filter 扩展模板功能
二、第一个模板:从 HttpResponse 到 render
1. 创建模板目录与文件

在项目根目录下创建 templates 目录,并新建 runoob.html:

HelloWorld/
├── HelloWorld/
│ ├── settings.py
│ ├── urls.py
│ ├── views.py
│ └── wsgi.py
├── manage.py
└── templates/
└── runoob.html

runoob.html 内容:

<h1>{{ hello }}</h1>

其中 {{ hello }} 就是模板变量,使用双大括号语法。

2. 配置模板路径

打开 settings.py,找到 TEMPLATES 配置,修改 DIRS:

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',
],
},
},
]

3. 编写视图函数

修改 views.py,使用 render 替代 HttpResponse:

from django.shortcuts import render

def runoob(request):
context = {}
context['hello'] = 'Hello World!'
return render(request, 'runoob.html', context)

render 的三个参数:

  • request:HTTP 请求对象(必须)。

  • 'runoob.html':模板文件路径。

  • context:传递给模板的上下文字典。字典的键对应模板中的变量名。

4. 配置 URL

from django.contrib import admin
from django.urls import path
from . import views

urlpatterns = [
path('admin/', admin.site.urls),
path('runoob/', views.runoob),
]

启动服务器,访问 http://127.0.0.1:8000/runoob,即可看到 Hello World! 被渲染到页面上。

三、模板变量
1. 基本用法

视图传值:

def runoob(request):
views_name = "教程"
return render(request, "runoob.html", {"name": views_name})

模板接收:

<p>{{ name }}</p>

2. 列表索引

Django 模板中使用 . 语法访问列表元素(注意不是 []):

def runoob(request):
views_list = ["教程1", "教程2", "教程3"]
return render(request, "runoob.html", {"views_list": views_list})

<p>{{ views_list }}</p> {# 取出整个列表 #}
<p>{{ views_list.0 }}</p> {# 取出第一个元素 #}

3. 字典取值

def runoob(request):
views_dict = {"name": "教程"}
return render(request, "runoob.html", {"views_dict": views_dict})

<p>{{ views_dict }}</p>
<p>{{ views_dict.name }}</p>

要点: Django 模板中的 . 是“万能取值符”,会依次尝试字典键、属性、列表索引,无需区分 [] 和 .。

四、过滤器

过滤器用于在变量输出前对其进行修改,语法为:

{{ 变量名 | 过滤器:可选参数 }}

1. 链式调用

过滤器可以套接,前一个的输出作为后一个的输入:

{{ my_list|first|upper }}

以上代码取列表第一个元素并转为大写。

2. 带参数的过滤器

参数跟随冒号,用双引号包裹:

{{ bio|truncatewords:"30" }}

3. 常用过滤器详解
过滤器作用示例
addslashes 在引号前添加反斜杠 {{ name|addslashes }}
date 格式化日期时间 {{ pub_date|date:"F j, Y" }}
length 返回长度 {{ name|length }}
default 变量为假时提供默认值 {{ name|default:"菜鸟教程666" }}
filesizeformat 易读的文件大小 {{ num|filesizeformat }}
truncatechars 截断字符串,以 … 结尾 {{ views_str|truncatechars:2 }}
safe 标记为安全,不转义 {{ views_str|safe }}

default 过滤器示例:

def runoob(request):
name = 0
return render(request, "runoob.html", {"name": name})

{{ name|default:"教程666" }}

以下值会被视为假(false),触发默认值:0、0.0、False、0j、""、[]、()、set()、{}、None。

length 过滤器示例:

def runoob(request):
name = "菜鸟教程"
return render(request, "runoob.html", {"name": name})

{{ name|length }}

字典返回键值对数量,集合返回去重后的长度。

filesizeformat 过滤器示例:

def runoob(request):
num = 1024
return render(request, "runoob.html", {"num": num})

{{ num|filesizeformat }}

输出类似 1.0 KB。

date 过滤器示例:

def runoob(request):
import datetime
now = datetime.datetime.now()
return render(request, "runoob.html", {"time": now})

{{ time|date:"Y-m-d" }}

输出如 2026-09-11。

truncatechars 过滤器示例:

{{ views_str|truncatechars:2 }}

输出 菜鸟…。

safe 过滤器(重点):

Django 默认会对变量中的 HTML 标签进行转义,防止 XSS 攻击。如果数据确实安全,可以用 safe 告诉 Django 不必转义:

def runoob(request):
views_str = "<a href='https://www.runoob.com/'>点击跳转</a>"
return render(request, "runoob.html", {"views_str": views_str})

{{ views_str|safe }}

安全提醒: 只有在你完全信任数据来源时才使用 safe,否则会引入 XSS 漏洞。

五、逻辑标签:if 与 for
1. if / elif / else

{% if condition1 %}
… display 1
{% elif condition2 %}
… display 2
{% else %}
… display 3
{% endif %}

支持 and、or、not 组合判断:

{% if athlete_list and coach_list %}
athletes 和 coaches 变量都是可用的。
{% endif %}

实例:

def runoob(request):
views_num = 88
return render(request, "runoob.html", {"num": views_num})

{% if num > 90 and num <= 100 %}
优秀
{% elif num > 60 and num <= 90 %}
合格
{% else %}
一边玩去~
{% endif %}

2. for 循环

<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>

反向迭代:

{% for i in views_list reversed %}
{{ i }}
{% endfor %}

遍历字典:

{% for i,j in views_dict.items %}
{{ i }}—{{ j }}
{% endfor %}

forloop 变量:

变量说明
forloop.counter 从 1 开始计数
forloop.counter0 从 0 开始计数
forloop.revcounter 倒序,结尾为 1
forloop.revcounter0 倒序,结尾为 0
forloop.first 第一条数据返回 True
forloop.last 最后一条数据返回 True

{% for i in listvar %}
{{ forloop.counter }} – {{ forloop.first }} – {{ forloop.last }}
{% endfor %}

empty 从句:

当循环对象为空时执行:

{% for i in listvar %}
{{ forloop.counter0 }}
{% empty %}
空空如也~
{% endfor %}

嵌套循环:

{% for athlete in athlete_list %}
<h1>{{ athlete.name }}</h1>
<ul>
{% for sport in athlete.sports_played %}
<li>{{ sport }}</li>
{% endfor %}
</ul>
{% endfor %}

六、注释、include 与 csrf_token

注释:

{# 这是一个注释 #}

include 标签:
将其他模板片段嵌入当前模板,常用于抽取导航栏、页脚:

{% include "nav.html" %}

csrf_token(表单必用):
在 form 表单中必须加上此标签,否则提交时会报 403 错误:

<form method="post">
{% csrf_token %}
<input type="text" name="username">
<button type="submit">提交</button>
</form>

工作原理: Django 的 CSRF 中间件会向登录页面注入一个隐藏的随机 token,表单提交时携带该 token,中间件校验通过才允许提交。

七、自定义标签与过滤器

当内置功能不够用时,可以自定义。步骤如下:

1. 在应用目录下创建 templatetags 目录(目录名固定,不能更改):

HelloWorld/
├── HelloWorld/
├── templatetags/
│ └── my_tags.py
├── manage.py
└── templates/

2. 创建 my_tags.py:

from django import template

register = template.Library() # register 名称固定,不可改变

3. 在 settings.py 中配置 libraries:

TEMPLATES = [
{
# …
'OPTIONS': {
'context_processors': [
# …
],
"libraries": {
'my_tags': 'templatetags.my_tags'
}
},
},
]

4. 定义过滤器(@register.filter):

@register.filter
def my_filter(v1, v2):
return v1 * v2

5. 定义标签(@register.simple_tag):

@register.simple_tag
def my_tag1(v1, v2, v3):
return v1 * v2 * v3

6. 在模板中导入并使用:

{% load my_tags %}

{{ 11|my_filter:22 }}

{% my_tag1 11 22 33 %}

7. 语义化标签:
使用 mark_safe 让返回的 HTML 生效:

from django.utils.safestring import mark_safe

@register.simple_tag
def my_html(v1, v2):
temp_html = "<input type='text' id='%s' class='%s' />" % (v1, v2)
return mark_safe(temp_html)

{% my_html "zzz" "xxx" %}

效果等同于前端过滤器的 safe。

八、配置静态文件

静态文件指 CSS、JavaScript、图片、插件等。配置步骤:

1. 在项目根目录下创建 statics 目录:

statics/
├── css/
├── js/
├── images/
└── plugins/

2. 在 settings.py 中配置:

STATIC_URL = '/static/' # URL 别名
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "statics"),
]

3. 在模板中加载静态文件:

{% load static %}
{{ name }}<img src="{% static 'images/runoob-logo.png' %}" alt="runoob-logo">

4. 引入外部框架(如 Bootstrap):

把 Bootstrap 放入 plugins 目录,然后在 HTML head 中引入。注意路径使用 static 别名而非目录名 statics:

<link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7/dist/css/bootstrap.css">

九、模板继承

模板继承是 Django 模板系统最强大的特性,用于消除页面中的重复结构。

父模板 base.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
<h1>Hello World!</h1>
<p>菜鸟教程 Django 测试。</p>
{% block mainbody %}
<p>original</p>
{% endblock %}
</body>
</html>

{% block mainbody %} 是预留区域,子模板可以替换它。

子模板 runoob.html:

{% extends "base.html" %}

{% block mainbody %}
<p>继承了 base.html 文件</p>
{% endblock %}

规则说明:

  • {% extends %} 必须是子模板的第一行标签。

  • 子模板只负责填充 block,不需要重复父模板的 HTML 结构。

  • 如果子模板不覆盖某个 block,则使用父模板的默认内容。

  • 不同 block 的名字不能相同。

模板继承流程图:

十、小结

本篇系统讲解了 Django 模板系统的核心内容:

  • 变量渲染:{{ variable }},支持字典、列表、对象属性访问。

  • 过滤器:{{ var|filter:arg }},常用有 default、length、date、safe 等。

  • 逻辑标签:{% if %}、{% for %},配合 forloop 和 {% empty %} 使用。

  • 模板继承:{% extends %} + {% block %},是消除重复 HTML 的最佳实践。

  • 静态文件:{% static %} 加载 CSS/JS/图片,需先配置 STATICFILES_DIRS。

  • 自定义标签与过滤器:通过 templatetags 目录扩展模板能力。

掌握这些内容后,你已经能够构建结构清晰、易于维护的前端页面。下一篇我们将进入 Django 的核心——Model 模型层,学习如何用 Python 类定义数据库表,并通过 ORM 完成数据的增删改查。

赞(0)
未经允许不得转载:网硕互联帮助中心 » Django入门教程(五):模板系统详解——变量、标签、过滤器与模板继承
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!