Django模板标签和过滤器

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

标签

if/else

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

{% if today_is_weekend %}
    

Welcome to the weekend!

{% endif %}

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

{% if today_is_weekend %}
   

Welcome to the weekend!

{% else %}

Get back to work.

{% endif %}

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

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

{% if athlete_list %}
    

Number of athletes: {{ athlete_list|length }}

{% elif athlete_in_locker_room_list %}

Athletes should be out of the locker room soon!

{% elif ... ... {% else %}

No athletes.

{% endif %}

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

{% if athlete_list and coach_list %}
    

Both athletes and coaches are available.

{% endif %} {% if not athlete_list %}

There are no athletes.

{% endif %} {% if athlete_list or coach_list %}

There are some athletes or some coaches.

{% endif %} {% if not athlete_list or coach_list %}

There are no athletes or there are some coaches.

{% endif %} {% if athlete_list and not coach_list %}

There are some athletes and absolutely no coaches.

{% 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:

    {% for athlete in athlete_list %}
  • {{ athlete.name }}
  • {% endfor %}

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

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

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

{% for athlete in athlete_list %}

{{ athlete.name }}

    {% for sport in athlete.sports_played %}
  • {{ sport }}
  • {% endfor %}
{% endfor %}

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

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

{% for x, y in points %}
    

There is a point at {{ x }},{{ y }}

{% endfor %}

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

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

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

{% if athlete_list %}
    {% for athlete in athlete_list %}
        

{{ athlete.name }}

{% endfor %} {% else %}

There are no athletes. Only computer programmers.

{% endif %}

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

{% for athlete in athlete_list %}
    

{{ athlete.name }}

{% empty %}

There are no athletes. Only computer programmers.

{% endfor %}

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

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

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

  • forloop.counter始终设置为表示循环已输入次数的整数。 这是一个索引,所以第一次通过循环,forloop.counter将被设置为1.下面是一个例子:
{% for item in todo_list %}
  

{{ forloop.counter }}: {{ item }}

{%endfor %}
  • forloop.counter0就像forloop.counter,除了它是零索引的。 它的值将在第一次通过循环设置为0。
  • forloop.revcounter始终设置为表示循环中剩余项目数的整数。 通过循环第一次,forloop.revcounter将被设置为您正在遍历的序列中的项目总数。 通过循环的最后一次,forloop.revcounter将被设置为1。
  • forloop.revcounter0就像forloop.revcounter,除了它是零索引。 通过循环第一次,forloop.revcounter0将被设置为序列中元素的个数减1。通过循环的最后一次,它将被设置为0。
  • forloop.first是一个布尔值,如果这是第一次通过循环,则设置为True。 这对于特殊外壳是很方便的:
{% for object in objects %}
    {% if forloop.first %}
        
  • {% else %}
  • {% endif %} {{ object }}
  • {% endfor %}
    • forloop.last是一个布尔值,如果这是通过循环的最后一次,则设置为True。 一个常见的用法是在一系列链接之间放置管道字符:
    {% for link in links %}
        {{ link }}{% if not forloop.last %} | {% endif %}
    {% endfor %}
    

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

      Link1 | Link2 | Link3 | Link4
    

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

    Favorite places:

    {% for p in places %} {{ p }}{% if not forloop.last %}, {% endif %} {% endfor %}

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

      {% for country in countries %}
      
          {% for city in country.city_list %}
          
          {% endfor %}
      
    Country #{{ forloop.parentloop.counter }} City #{{ forloop.counter }} {{ city }}
    {% 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涵盖了其余部分。

    • addslashes:在任何反斜杠,单引号或双引号之前添加反斜杠。 这对于转义字符串非常有用。 例如:{{value | addslashes}}。

    • date:根据参数中给定的格式字符串格式化日期或日期时间对象。 例如:{{pub_date | date:“F j,Y”}}格式字符串在附录E中定义。

    • length:返回值的长度。 对于一个列表,这将返回元素的数量。 对于一个字符串,这将返回字符的数量。 如果变量未定义,则长度返回0。

    哲学与局限

    现在您已经了解了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更为方便,但是从任何意义上讲,这并不是一个严格的要求。

    你可能感兴趣的:(Django模板标签和过滤器)