Python 学习笔记

Django模板标签和过滤器

2018-01-28  本文已影响24人  大爷的二舅

正如我已经提到的,模板系统带有内置的标签和过滤器。 下面的部分提供了最常用的标签和过滤器的简要介绍。

标签

if/else

{%if%}标签评估一个变量,如果这个变量是“真”(即它存在,不是空的,而不是一个错误的布尔值),系统将显示{%if%}和 {%endif%},例如:

{% if today_is_weekend %}
    <p>Welcome to the weekend!</p>
{% endif %}

一个{%else%}标记是可选的:

{% if today_is_weekend %}
   <p>Welcome to the weekend!</p>
{% else %}
   <p>Get back to work.</p>
{% endif %}

确保使用{%endif%}关闭每个{%if%},否则Django将抛出一个TemplateSyntaxError。

if标签也可以带一个或多个{%elif%}子句:

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

{%if%}标签接受and,or,or not用于测试多个变量,或者否定给定的变量。 例如:

{% if athlete_list and coach_list %}
    <p>Both athletes and coaches are available.</p>
{% endif %}

{% if not athlete_list %}
    <p>There are no athletes.</p>
{% endif %}

{% if athlete_list or coach_list %}
    <p>There are some athletes or some coaches.</p>
{% endif %}

{% if not athlete_list or coach_list %}
    <p>There are no athletes or there are some coaches.</p>
{% endif %}

{% if athlete_list and not coach_list %}
    <p>There are some athletes and absolutely no coaches.</p>
{% endif %}

在同一个标签内使用and和or子句是允许的,并且具有更高的优先权。

{% if athlete_list and coach_list or cheerleader_list %}

将被解释为:

if (athlete_list and coach_list) or cheerleader_list
在if标记中使用实际的括号是无效的语法。

如果你需要括号来表示优先级,你应该使用嵌套的if标签。 不支持使用括号来控制操作顺序。 如果您发现自己需要括号,请考虑在模板之外执行逻辑,并将其结果作为专用模板变量传递。 或者,只需使用嵌套的{%if%}标签。

同一逻辑运算符的多次使用都可以,但不能组合不同的运算符。 例如,这是有效的:

{% if athlete_list or coach_list or parent_list or teacher_list %}

{%if%}也接受in / not in来测试一个给定的值是否在指定的容器中,is/is not 是用来测试两个实体是否是相同的对象。
例如:

{% if "bc" in "abcdef" %}
    This appears since "bc" is a substring of "abcdef"
{% endif %}

{% if user not in users %}
    If users is a list, this will appear if user isn't an element of the list.
{% endif %}

{% if somevar is True %}
    This appears if and only if somevar is True.
{% endif %}

{% if somevar is not None %}
    This appears if somevar isn't None.
{% endif %}
for

{%for%}标签允许您循环顺序中的每个项目。 就像在Python for语句中一样,语法是for Y in X,其中Y是循环的序列,X是用于循环的特定循环的变量的名称。 每次循环时,模板系统都会呈现{%for%}和{%endfor%}之间的所有内容。 例如,您可以使用以下内容来显示运动员列表,给出一个变量athlete_list:

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

添加反向标签用于反向遍历列表:

{% for athlete in athlete_list reversed %}
...
{% endfor %}

可以嵌套{%for%}标签:

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

如果您需要遍历一系列的列表,则可以将每个子列表中的值解包为单个变量。

例如,如果您的上下文包含(x,y)的坐标点的坐标列表,则可以使用以下内容输出点列表:

{% for x, y in points %}
    <p>There is a point at {{ x }},{{ y }}</p>
{% endfor %}

如果您需要访问字典中的项目,这也可能很有用。 例如,如果您的上下文包含字典数据,则以下内容将显示字典的键和值:

{% for key, value in data.items %}
    {{ key }}: {{ value }}
{% endfor %}

一个常见的模式是在循环之前检查列表的大小,如果列表为空则输出一些特殊的文本:

{% if athlete_list %}
    {% for athlete in athlete_list %}
        <p>{{ athlete.name }}</p>
    {% endfor %}
{% else %}
    <p>There are no athletes. Only computer programmers.</p>
{% endif %}

因为这个模式非常常见,所以for标签支持一个可选的{%empty%}子句,可以让你定义如果列表为空时要输出的内容。 这个例子相当于前一个例子:

{% for athlete in athlete_list %}
    <p>{{ athlete.name }}</p>
{% empty %}
    <p>There are no athletes. Only computer programmers.</p>
{% endfor %}

在循环结束之前不支持“breaking out”循环。 如果你想完成这个,改变你正在循环的变量,这样它只包含你想循环的值。

同样,不支持“continue”语句,指示循环处理器立即返回到循环的前面。 (请参阅本章后面的“哲学和限制”一节,以了解设计决策背后的原因。)

在每个{%for%}循环中,您可以访问一个名为forloop的模板变量。 这个变量有几个属性给你提供关于循环进度的信息:

{% for item in todo_list %}
  <p>{{ forloop.counter }}: {{ item }}</p>
{%endfor %}
{% for object in objects %}
    {% if forloop.first %}
        <li class="first">
    {% else %}
        <li>
    {% endif %}
    {{ object }}</li>
{% endfor %}
{% for link in links %}
    {{ link }}{% if not forloop.last %} | {% endif %}
{% endfor %}

上面的模板代码可能会输出如下所示:

  Link1 | Link2 | Link3 | Link4

另一个常用的用法是在单词之间加一个逗号,

<p>Favorite places:</p>
{% for p in places %}
    {{ p }}{% if not forloop.last %}, {% endif %}
{% endfor %}

forloop.parentloop是嵌套循环的父循环的forloop对象的引用。 这是一个例子:

  {% for country in countries %}
  <table>
      {% for city in country.city_list %}
      <tr>
          <td>Country #{{ forloop.parentloop.counter }}</td>
          <td>City #{{ forloop.counter }}</td>
          <td>{{ city }}</td>
      </tr>
      {% endfor %}
  </table>
  {% endfor %}

for循环变量仅在循环中可用。 在模板解析器达到{% endfor %},for循环消失。

ifequal/ifnotequal

{%ifequal%} / {%endifequal%}和{%ifnotequal%} / {%endifnotequal%}是过时的写法{%if a == b%} / {%endif%}和{%if a! = b%} / {%endif%}布尔运算符。 从这个第二版中删除了对这些废弃标签的引用。
有关Django模板中布尔比较标签的更多信息,请参阅附录E.

注释

就像在HTML或Python中一样,Django模板语言允许注释。 要指定注释,请使用{##}:

{# This is a comment #}

渲染模板时不会输出注释。 使用此语法的注释不能跨越多行。 此限制提高了模板解析性能。

在以下模板中,呈现的输出将与模板完全相同(即,注释标记不会被解析为注释):

This is a {# this is not
a comment #}
test.

如果您想使用多行注释,请使用{%comment%}模板标签,如下所示:

{% comment %}
This is a
multi-line comment.
{% endcomment %}

注释标签可能包含一个可选的注释(例如为了解释为什么这段代码会被注释掉):

{% comment "This is the optional note" %}
    ...
{% endcomment %}

注释标签不能嵌套。

过滤器

正如本章前面所解释的,模板过滤器是在变量显示之前更改变量值的简单方法。 过滤器使用管道字符,如下所示:

{{ name|lower }}

这将显示{{name}}变量的值,通过将文本转换为小写的下层过滤器进行过滤。 过滤器可以链接 - 也就是说,它们可以串联使用,以便将一个过滤器的输出应用于下一个过滤器。

下面是一个例子,它将列表中的第一个元素转换为大写字母:

{{ my_list|first|upper }}

一些过滤器需要参数。 过滤器参数出现在冒号后面,并始终使用双引号。 例如:

{{ bio|truncatewords:"30" }}

这显示bio变量的前30个单词。

以下是几个最重要的过滤器。 附录E涵盖了其余部分。

哲学与局限

现在您已经了解了Django模板语言(DTL),现在可能是时候解释DTL背后的基本设计理念了。

首先,对DTL的限制是有意的。

Django是在一个在线新闻编辑的高容量,不断变化的环境中开发的。 Django的原创者在创建DTL时有一套非常明确的哲学。

这些哲学今天仍然是Django的核心。 他们是:

  1. 与演示分开的逻辑
  2. 不鼓励冗余
  3. 从HTML解耦
  4. XML是不好的
  5. 假设设计师很有才干
  6. 明显地对待空白
  7. 不要发明一种编程语言
  8. 确保安全
  9. 扩展
1.与演示分开的逻辑

模板系统是控制表示和表示相关逻辑的工具,就是这样。 模板系统不应该支持超出这个基本目标的功能。

2.不鼓励冗余

大多数动态网站使用某种常见的站点范围的设计 - 常见的页眉,页脚,导航条等。Django模板系统应该可以轻松地将这些元素存储在一个地方,消除重复的代码。这是模板继承的哲学。

3.从HTML中解耦

模板系统不应该被设计成只输出HTML。它应该同样适用于生成其他基于文本的格式,或只是纯文本。

4. XML不应该用于模板语言

使用XML引擎解析模板引入了编辑模板中人为错误的全新世界 - 并且在模板处理中产生了不可接受的开销水平。

5.假设设计师的能力

不应将模板系统设计为使模板必须在所见即所得编辑器(如Dreamweaver)中很好地显示。这是太严格的限制,并不会让语法像它一样好。

Django期望模板作者可以直接编辑HTML。

6.明显地对待空白

模板系统不应该用空白做一些神奇的事情。如果一个模板包含空格,那么系统应该将空格视为对待文本 - 只显示它。应该显示不在模板标签中的任何空格。

7.不要发明一种编程语言

模板系统有意不允许以下内容:

  1. 赋值给变量
  2. 先进的逻辑
    目标不是发明一种编程语言。 目标是提供足够的编程风格的功能,如分支和循环,这是做出演示相关的决定的关键。

Django模板系统认识到模板通常是由设计者编写的,而不是程序员,因此不应该承担Python的知识。

8.安全和保障

开箱即用的模板系统应该禁止包含恶意代码 - 例如删除数据库记录的命令。 这是模板系统不允许任意执行Python代码的另一个原因。

9.可扩展性

模板系统应该认识到高级模板作者可能想要扩展它的技术。 这是自定义模板标签和过滤器背后的原理。

DTL哲学 - 总结性思考

多年来,我一直与许多不同的模板系统合作过,我全心全意地赞同这种方法 - DTL和它的设计方式是Django框架的主要特性之一。

当你面临完成Get Stuff的压力时,设计师和程序员都试图沟通并完成所有最后一分钟的任务,Django只是让开发工作,让每个团队专注于自己擅长的领域。

一旦你通过真实的练习找到了自己的想法,你会很快发现Django为什么是“完美主义者的期限框架”。

模板语法比任何其他Web应用程序组件都更具主观性,程序员的观点差异很大。仅Python就有数十个,甚至数百个开源模板语言实现支持这一点。由于开发者认为所有现有的模板语言都不够完善,

考虑到这一切,Django是灵活的 - 它不需要你使用DTL。 Django的所有最新版本,包括Django 1.11,都附带了流行的Jinja2模板引擎以及为开发人员提供选项的DTL。

由于Django旨在成为一个完整的Web框架,为Web开发人员提供所需的所有功能,所以大多数情况下使用DTL更为方便,但是从任何意义上讲,这并不是一个严格的要求。

上一篇下一篇

猜你喜欢

热点阅读