Django 模板语言

您所在的位置:网站首页 字典套字典 Django 模板语言

Django 模板语言

2023-07-03 16:21| 来源: 网络整理| 查看: 265

Django 模板语言¶

本文档解释了 Django 模板系统的语言语法。如果你想从技术角度了解它的工作原理以及如何扩展它,请参见 Django 模板语言:对于 Python 开发者。

Django 的模板语言是为了在强大和简单之间取得平衡而设计的。它的设计让习惯于使用 HTML 的人感觉很舒服。如果你接触过其他基于文本的模板语言,如 Smarty 或 Jinja2 ,你应该会对 Django 的模板感到很舒服。

设计哲学

如果你有编程背景,或者你习惯于将编程代码直接混入 HTML 的语言,你要记住,Django 模板系统并不是简单的将 Python 嵌入到 HTML 中。这是设计上的:模板系统是为了表达表现形式,而不是程序逻辑。

Django 模板系统提供了类似于一些编程结构的标签——布尔测试的 if 标签,循环的 for 标签等等。——但这些并不是简单地作为相应的 Python 代码来执行,模板系统不会执行任意的 Python 表达式。默认情况下只支持下面列出的标签、过滤器和语法(尽管你可以根据需要在模板语言中添加 你自己的扩展)。

模板¶

模板是一个文本文件。它可以生成任何基于文本的格式(HTML、XML、CSV 等)。

一个模板包含 变量 和 标签,前者在模板被执行时被替换为值,后者控制模板的逻辑。

下面是一个最小的模板,说明了一些基本的内容。每一个元素将在本文档的后面解释。

{% extends "base_generic.html" %} {% block title %}{{ section.title }}{% endblock %} {% block content %} {{ section.title }} {% for story in story_list %} {{ story.headline|upper }} {{ story.tease|truncatewords:"100" }} {% endfor %} {% endblock %}

设计哲学

为什么使用基于文本的模板而不是基于 XML 的模板(比如 Zope 的 TAL)?我们希望 Django 的模板语言不仅仅适用于 XML/HTML 模板。你可以将模板语言用于任何基于文本的格式,如电子邮件、JavaScript 和 CSV。

变量¶

Variables look like this: {{ variable }}. When the template engine encounters a variable, it evaluates that variable and replaces it with the result. Variable names consist of any combination of alphanumeric characters and the underscore ("_") but may not start with an underscore, and may not be a number. The dot (".") also appears in variable sections, although that has a special meaning, as indicated below. Importantly, you cannot have spaces or punctuation characters in variable names.

使用点号(.)来访问一个变量的属性。

幕后

从技术上讲,当模板系统遇到一个点时,它会按照以下顺序尝试进行查找:

字典查找 属性或方法查找 数字索引查找

如果产生的值是可调用对象,则调用时不含参数。调用的结果成为模板值。

This lookup order can cause some unexpected behavior with objects that override dictionary lookup. For example, consider the following code snippet that attempts to loop over a collections.defaultdict:

{% for k, v in defaultdict.items %} Do something with k and v here... {% endfor %}

因为字典查找是先发生的,这种行为会启动并提供一个默认值,而不是使用预期的 .items() 方法。在这种情况下,可以考虑先转换为字典。

在上面的例子中,{{ section.title }} 将被 section 对象的 title 属性所取代。

如果你使用一个不存在的变量,模板系统会插入 string_if_invalid 选项的值,默认设置为 '' (空字符串)。

请注意,像 {{ foo.bar }} 这样的模板表达式中的“bar”将被解释为一个字面字符串,而不是使用变量“bar”的值,如果模板上下文中存在的话。

以下划线开头的变量属性可能不会被访问,因为它们通常被认为是私有的。

过滤器¶

你可以通过使用 过滤器 修改显示的变量。

过滤器是这样的: {{ name|lower }}。这将显示 lower 过滤器过滤后的 {{ name }} 变量的值,该过滤器将文本转换为小写。使用管道(|)来应用过滤器。

过滤器可以“链式的”。一个过滤器的输出被应用到下一个过滤器。{{ text|escape|linebreaks }} 是一个常用的成语,用于转义文本内容,然后将换行符转换为

标签。

有些过滤器需要参数。一个过滤器的参数是这样的: {{ bio|truncatewords:30 }}。这将显示 bio 变量的前 30 个字。

包含空格的过滤器参数必须加引号;例如,要连接一个包含逗号和空格的列表,你可以使用 {{ list|join:", " }}。

Django 提供了大约 60 个内置的模板过滤器。你可以在 内置过滤器参考 中阅读它们。为了让你了解这些模板过滤器,这里有一些比较常用的模板过滤器:

default

If a variable is false or empty, use given default. Otherwise, use the value of the variable. For example:

{{ value|default:"nothing" }}

如果 value 没有提供或者为空,那么他将显示为“nothing”。

length

Returns the length of the value. This works for both strings and lists. For example:

{{ value|length }}

如果 value 为 ['a', 'b', 'c', 'd'], 那么他将被显示为 4。

filesizeformat

Formats the value like a "human-readable" file size (i.e. '13 KB', '4.1 MB', '102 bytes', etc.). For example:

{{ value|filesizeformat }}

如果 value 是 123456789,则输出为 117.7 MB。

这些只是几个例子,请参阅 内置过滤器参考 的完整列表。

你还可以创建自己的自定义模板过滤器,请参见 如何编写自定义的模板标签和过滤器。

参见

Django 的管理界面可以包含一个完整的给定网站的所有模板标签和过滤器的参考。参见 Django 管理文档生成器。

标签¶

标签是这样的: {% tag %}。标签比变量更复杂。有的在输出中创建文本,有的通过执行循环或逻辑来控制流程,有的将外部信息加载到模板中,供以后的变量使用。

有些标签要求有开始和结束标签(即 {% tag %} ... tag contents ... {% endtag %})。

Django 有二十多个内置的模板标签。你可以在 内置标签参考 中阅读所有关于它们的信息。为了让你了解这些标签,这里有一些比较常用的标签。

for

Loop over each item in an array. For example, to display a list of athletes provided in athlete_list:

{% for athlete in athlete_list %} {{ athlete.name }} {% endfor %} if、elif 和 else

Evaluates a variable, and if that variable is "true" the contents of the block are displayed:

{% if athlete_list %} Number of athletes: {{ athlete_list|length }} {% elif athlete_in_locker_room_list %} Athletes should be out of the locker room soon! {% else %} No athletes. {% endif %}

在上述情况下,如果 athlete_list 不为空,则会通过 { athlete_list|length }} 变量显示运动员的数量。否则,如果 athlete_in_locker_room_list 不为空,则会显示“Athletes should be out...”的消息。如果两个列表都是空的,将显示“No athletes.”。

You can also use filters and various operators in the if tag:

{% if athlete_list|length > 1 %} Team: {% for athlete in athlete_list %} ... {% endfor %} {% else %} Athlete: {{ athlete_list.0.name }} {% endif %}

虽然上面的例子是可行的,但要注意大多数模板过滤器都会返回字符串,所以使用过滤器进行数学比较一般不会像你预期的那样。

block 和 extends设置 模板继承 (见下文),这是减少模板中 “样板代码” 的有力方法。

同样,以上只是整个列表的一部分,完整的列表请参见 内置标签参考。

你也可以创建你自己的模板标签;参见 如何编写自定义的模板标签和过滤器。

参见

Django 的管理界面可以包含一个完整的给定网站的所有模板标签和过滤器的参考。参见 Django 管理文档生成器。

注释¶

要对模板中的部分行进行注释,请使用注释语法。{# #}。

For example, this template would render as 'hello':

{# greeting #}hello

A comment can contain any template code, invalid or not. For example:

{# {% if foo %}bar{% else %} #}

这种语法只能用于单行注释(在 {# 和 #} 定界符之间不允许使用换行)。如果你需要对模板的多行部分进行注释,请参见 comment 标签。

模板继承¶

Django 的模板引擎中最强大的——也是最复杂的——部分是模板继承。模板继承允许你建立一个基本的“骨架”模板,它包含了你网站的所有常用元素,并定义了子模板可以覆盖的 块。

Let's look at template inheritance by starting with an example:

{% block title %}My amazing site{% endblock %} {% block sidebar %} Home Blog {% endblock %} {% block content %}{% endblock %}

这个模板,我们称之为 base.html,它定义了一个 HTML 骨架文档,你可以用它来制作一个两栏式页面。“子”模板的工作是用内容填充空块。

在这个例子中,block 标签定义了三个块,子模板可以填入其中。block 标签所做的就是告诉模板引擎,子模板可以覆盖模板的这些部分。

A child template might look like this:

{% extends "base.html" %} {% block title %}My amazing blog{% endblock %} {% block content %} {% for entry in blog_entries %} {{ entry.title }} {{ entry.body }} {% endfor %} {% endblock %}

extends 标签是这里的关键。它告诉模板引擎,这个模板“扩展”了另一个模板。当模板系统执行这个模板时,首先要找到父模板——在本例中是“base.html”。

At that point, the template engine will notice the three block tags in base.html and replace those blocks with the contents of the child template. Depending on the value of blog_entries, the output might look like:

My amazing blog Home Blog Entry one This is my first entry. Entry two This is my second entry.

请注意,由于子模板没有定义 sidebar 块,所以使用父模板的值来代替。父模板中 {% block %} 标签中的内容总是被用作后备。

你可以根据需要使用任意层次的继承。一种常见的使用继承的方式是像以下的三层继承:

创建一个 base.html 模板,以保持你网站的主要外观和风格。 为你网站的每个“部分”创建一个 base_SECTIONNAME.html 模板。例如,base_news.html、base_sports.html。这些模板都是对 base.html 的扩展,并包括特定部分的样式/设计。 为每种类型的页面创建单独的模板,如新闻文章或博客条目。这些模板扩展了相应的部分模板。

这种方法可以最大限度地重用代码,并有助于将项目添加到共享内容区域,如全部分导航。

下面是一些关于继承工作的技巧:

如果你在模板中使用 {% extends %},它必须是该模板中的第一个模板标签。否则,模板继承将无法使用。

基础模板中的 {% block %} 标签越多越好。记住,子模板不需要定义所有的父块,所以你可以在一些块中填入合理的默认值,然后只定义以后需要的块。钩子多比钩子少好。

如果你发现自己的内容在多个模板中重复,可能意味着你应该把这些内容移到父模板中的 {% block %}。

如果你需要从父模板中获取块的内容,{{ block.super }} 变量就可以做到这一点。如果你想添加到父模板的内容中,而不是完全覆盖它,这很有用。使用 {{ block.super }} 插入的数据不会被自动转义(参见 下一节 ),因为如果需要的话,它已经在父模板中被转义了。

通过使用与继承模板相同的模板名称,{% extends %} 可以在覆盖模板的同时继承它。结合 {{ block.super }},这可以成为一种强大的小规模定制方式。完整的例子请参见 扩展复写模板 中的 Overriding templates How-to。

Variables created outside of a {% block %} using the template tag as syntax can't be used inside the block. For example, this template doesn't render anything:

{% translate "Title" as title %} {% block content %}{{ title }}{% endblock %}

For extra readability, you can optionally give a name to your {% endblock %} tag. For example:

{% block content %} ... {% endblock content %}

在较大的模板中,这种技术可以帮助你看到哪些 {% block %} 标签正在被关闭。

{% block %} tags are evaluated first. That's why the content of a block is always overridden, regardless of the truthiness of surrounding tags. For example, this template will always override the content of the title block:

{% if change_title %} {% block title %}Hello!{% endblock title %} {% endif %}

最后,请注意,你不能在同一个模板中定义多个同名的 block 标签。之所以有这种限制,是因为块标签可以“双向”工作。也就是说,一个块标签不只是提供一个洞来填补——它还定义了填补 父 模板中洞的内容。如果一个模板中有两个名称相似的 block 标签,那么该模板的父标签就不知道该使用哪一个块的内容。

自动 HTML 转义¶

When generating HTML from templates, there's always a risk that a variable will include characters that affect the resulting HTML. For example, consider this template fragment:

Hello, {{ name }}

At first, this seems like a harmless way to display a user's name, but consider what would happen if the user entered their name as this:

alert('hello')

With this name value, the template would be rendered as:

Hello, alert('hello')

...这意味着浏览器会弹出一个 JavaScript 提示框!

同样,如果名称中包含一个 '



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3