美文网首页Python 学习笔记
Django模板标签和过滤器

Django模板标签和过滤器

作者: 大爷的二舅 | 来源:发表于2018-01-28 23:06 被阅读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的模板变量。 这个变量有几个属性给你提供关于循环进度的信息:

    • forloop.counter始终设置为表示循环已输入次数的整数。 这是一个索引,所以第一次通过循环,forloop.counter将被设置为1.下面是一个例子:
    {% for item in todo_list %}
      <p>{{ forloop.counter }}: {{ item }}</p>
    {%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 %}
            <li class="first">
        {% else %}
            <li>
        {% endif %}
        {{ object }}</li>
    {% endfor %}
    
    • forloop.last是一个布尔值,如果这是通过循环的最后一次,则设置为True。 一个常见的用法是在一系列链接之间放置管道字符:
    {% 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涵盖了其余部分。

    • 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模板标签和过滤器

        本文链接:https://www.haomeiwen.com/subject/nxftzxtx.html