Django 模板系统:配置、继承与安全处理
模板文件工作流程
模板引擎主要参与模板渲染的系统。 内容源:输入的数据流,常见的有数据库、XML 文件和用户请求这样的网络数据。 模板:一般是和语言相关的文本。
工作流程涉及模板引擎根据上下文对模板中的变量进行替换,并根据操作标签来执行操作,输出文本。
作为一个 Web 框架,Django 自带了一套模板系统动态生成 HTML 文本。模板主要包含两个部分:HTML 的静态部分和描述如何插入动态内容的特殊语法。
Django 模板系统通过配置引擎、定义变量标签及过滤器实现动态内容渲染。支持模板继承结构优化代码复用,内置自动转义机制防御 XSS 攻击。开发者可自定义标签与过滤器扩展功能,结合 settings.py 配置灵活管理模板路径与后端。

模板引擎主要参与模板渲染的系统。 内容源:输入的数据流,常见的有数据库、XML 文件和用户请求这样的网络数据。 模板:一般是和语言相关的文本。
工作流程涉及模板引擎根据上下文对模板中的变量进行替换,并根据操作标签来执行操作,输出文本。
作为一个 Web 框架,Django 自带了一套模板系统动态生成 HTML 文本。模板主要包含两个部分:HTML 的静态部分和描述如何插入动态内容的特殊语法。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
模板的配置在 settings.py 当中实现。
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['/var/www/html/site.com', '/var/www/html/default'],
},
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': '/var/www/html/another_app'
}
]
TEMPLATES 变量是一个列表,包含多个字典,每个字典定义了一组模板配置。这些配置告诉 Django 如何渲染模板。
TEMPLATES = [...]:定义了一个名为 TEMPLATES 的列表,其中包含多个模板配置。'BACKEND': 'django.template.backends.django.DjangoTemplates':指定使用 Django 自带的模板引擎。这是 Django 默认的模板引擎,它基于 Python 编写。'DIRS': [...]:定义了一个目录列表,Django 会在这些目录中查找模板文件。'BACKEND': 'django.template.backends.jinja2.Jinja2':指定使用 Jinja2 模板引擎。Jinja2 是一个流行的 Python 模板引擎,它支持更复杂的模板语法和功能。'DIRS': '/var/www/html/another_app':定义了一个单一的目录,Django 会在该目录中查找 Jinja2 模板文件。通过这种配置,Django 项目可以同时使用 Django 自带的模板引擎和 Jinja2 模板引擎,从而提供更大的灵活性和选择。
模板引擎可以识别模板中的特殊结构,以动态生成文本。主要的特殊结构有变量和标签。
Django 的模板语言当中包含了四种结构:变量、标签、过滤器和注释。
变量用于在模板中显示来自视图(view)传递的数据。变量通常以双大括号 {{ }} 包裹。例如:
<p>Hello, {{ name }}!</p>
如果 name 的值是 "Alice",那么模板渲染后会显示:
<p>Hello, Alice!</p>
标签用于控制模板的逻辑,例如循环、条件判断、加载外部模板等。标签以 {% %} 包裹。常见的标签包括:
{% if %}:条件判断{% for %}:循环{% include %}:加载外部模板{% extends %} 和 {% block %}:模板继承例如:
{% if user.is_authenticated %}
<p>Welcome, {{ user.username }}!</p>
{% else %}
<p>Please login.</p>
{% endif %}
过滤器用于对变量进行格式化或转换。过滤器通过管道符号 | 应用到变量上。例如:
<p>{{ date|date:"Y-m-d" }}</p>
如果 date 是一个 datetime 对象,过滤器会将其格式化为指定的格式。Django 内置了许多过滤器,如 upper、lower、truncatewords 等。
模板注释用于在模板中添加说明性内容,这些内容在渲染时会被忽略。Django 模板注释使用 {# #} 包裹。例如:
{# This is a comment in the template #}
<p>Hello, {{ name }}!</p>
在真实开发环境下,不乏不同网页结构和样式一样的情况,为减少重复,增加可维护性,我们会使用模板继承。
基础模板定义了页面的通用结构,包括 HTML 的基本骨架、头部、尾部、导航栏等。你可以在基础模板中定义一些'块'(block),这些块可以在子模板中被覆盖。
<!-- base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
{% block title %}<title>Default Title</title>{% endblock %}
</head>
<body>
<div>
<ul>
<li>主页</li>
<li>帮助</li>
</ul>
</div>
<div>
{% block content %}
<!-- 默认内容 -->
{% endblock %}
</div>
<footer>我是页脚</footer>
</body>
</html>
子模板通过使用 {% extends %} 标签来继承基础模板。然后,子模板可以使用 {% block %} 标签来覆盖基础模板中定义的块。
<!-- home.html -->
{% extends "base.html" %}
{% block title %}<title>主页</title>{% endblock %}
{% block content %}
<h1>欢迎来到主页!</h1>
<p>虽然这个网站什么内容都没有,但是它展示了使用模板继承的用法。</p>
{% endblock %}
在你的 Django 视图函数中,你需要指定使用哪个模板来渲染页面。
from django.shortcuts import render
def home(request):
return render(request, 'home.html')
当 Django 的模板引擎处理 home.html 时,它会首先加载 base.html,然后查找 home.html 中定义的块,并用这些块替换 base.html 中的相应块。最终,模板引擎会生成一个完整的 HTML 页面,其中包含了基础模板的结构和子模板的特定内容。
常见的网站模板继承结构往往是三级的,通常用于提高代码复用性和维护效率。
示例结构:
base.html (Level 1)user_center.html (Level 2, extends base.html)user_profile.html (Level 3, extends user_center.html)这种三级模板继承结构的优点包括:
在 HTML 模板渲染中,如果直接将用户输入的内容插入到 HTML 中,而没有进行适当的转义或过滤,就可能引发 XSS(跨站脚本)攻击。XSS 攻击是一种安全漏洞,攻击者通过在用户输入中嵌入恶意代码(如 JavaScript 脚本),当这些代码被渲染到页面上时,就会在用户的浏览器中执行。
例如:
你好,{{ username }}
如果用户将用户名设置为 <script>alert('一次攻击')</script>,那么渲染后的 HTML 就会变成:
你好,<script>alert('一次攻击')</script>
当页面加载时,浏览器会执行这段 JavaScript 代码。
XSS 攻击主要有两种类型:
使用 Django 处理这种问题有两种选择:
escape 过滤。具体地说,5 个字符串会被自动转义:< 变为 <,> 变为 >,单引号变为 ',双引号变为 ",& 变为 &。
Django 几乎为所有的行为都提供配置,转义自然也不例外。有时候模板变量包含开发者打算作为原始 HTML 呈现的数据,那么这时可能希望内容不被转义。
要想对单个变量关闭自动转义功能,则可以使用 safe 过滤器:
{{ data }} <!-- 会转义 -->
{{ data|safe }} <!-- 不会转义 -->
另外,也可以控制对模板的自动转义,这时要用到 autoescape 标签:
{% autoescape off %}
这个不会被自动转义 {{ data }}.
{% endautoescape %}
重新开启自动转义 {{ name }}
{% endautoescape %}
这个也不会被自动转义 {{ other_data }}
需要注意的是,过滤器是支持字符串作为参数的。这些字符串并不会被自动转义。
自定义标签和过滤器应该统一放在一个文件当中——为此,可以在应用目录下创建一个 templatetags 文件夹。
text
myapp/
├── __init__.py
├── models.py
├── templatetags/
│ ├── __init__.py
│ └── customize.py
├── tests.py
└── views.py
templatetags 文件夹。templatetags 文件夹内创建空的 __init__.py 文件。customize.py。在 customize.py 文件中定义自定义标签。例如:
from django import template
register = template.Library()
@register.simple_tag
def hello_name(name):
return f"Hello, {name}!"
在模板中使用 {% load %} 标签加载自定义标签库:
{% load customize %}
<p>{% hello_name "Alice" %}</p>
编写自定义过滤器与编写自定义标签类似,但过滤器用于处理模板变量的值。
from django import template
register = template.Library()
@register.filter(name='upper')
def upper(value):
return value.upper()
@register.filter(name='lower')
def lower(value):
return value.lower()
在模板中使用:
{% load customize %}
<p>{{ my_string|upper }}</p>
<p>{{ my_string|lower }}</p>
创建和注册过程相似:
templatetags 目录。template 模块。Library 实例。@register.tag 或 @register.filter 装饰器注册。