6.2 模板标签和过滤器基础

我们已经提到模板系统使用内建的标签和过滤器,这里我们看看常见的。

6.2.1 if/else

{% if %} 标签计算一个变量值,如果是 true,即它存在、不为空并且不是 false 的布尔值

系统则会显示 {% if %}{% endif %} 间的所有内容:

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

{% if %} 标签接受 andor 或者 not 来测试多个变量值或者否定一个给定的变量,例如:

  1. {% if athlete_list and coach_list %}
  2. Both athletes and coaches are available.
  3. {% endif %}
  4. {% if not athlete_list %}
  5. There are no athletes.
  6. {% endif %}
  7. {% if athlete_list or coach_list %}
  8. There are some athletes or some coaches.
  9. {% endif %}
  10. {% if not athlete_list or coach_list %}
  11. There are no athletes or there are some coaches.
  12. {% endif %}
  13. {% if athlete_list and not coach_list %}
  14. There are some athletes and absolutely no coaches.
  15. {% endif %}

{% if %} 标签 && 等同于 and|| 等同于 or

  1. {% if user.is_moderator && (user.moderation_level > 2 || user.moderation_level <= 0) %}
  2. ...
  3. {% else %}
  4. ...
  5. {% endif %}

如果你想结合 andor 来做高级逻辑,只需使用嵌套的 {% if %} 标签即可:

  1. {% if athlete_list %}
  2. {% if coach_list or cheerleader_list %}
  3. We have athletes, and either coaches or cheerleaders!
  4. {% endif %}
  5. {% endif %}

多次使用同一个逻辑符号是合法的:

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

没有 {% elif %} 标签,使用嵌套的 {% if %} 标签可以做到同样的事情:

  1. {% if athlete_list %}
  2. <p>Here are the athletes: {{ athlete_list }}.</p>
  3. {% else %}
  4. <p>No athletes are available.</p>
  5. {% if coach_list %}
  6. <p>Here are the coaches: {{ coach_list }}.</p>
  7. {% endif %}
  8. {% endif %}

注: 必须使用 {% endif %} 来关闭 {% if %} 标签。

6.2.2 for

{% for %} 标签允许你按顺序遍历一个序列中的各个元素

Go的for语句语法为 for X in Y ,X 是用来遍历 Y 的变量

每次循环模板系统都会渲染 {% for %}{% endfor %} 之间的所有内容

例如,显示给定athlete_list变量来显示athlete列表:

  1. <ul>
  2. {% for athlete in athlete_list %}
  3. <li>{{ athlete.name }}</li>
  4. {% endfor %}
  5. </ul>

在标签里添加 reversed 来反序循环列表:

  1. {% for athlete in athlete_list reversed %}
  2. ...
  3. {% endfor %}

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

  1. {% for country in countries %}
  2. <h1>{{ country.name }}</h1>
  3. <ul>
  4. {% for city in country.city_list %}
  5. <li>{{ city }}</li>
  6. {% endfor %}
  7. </ul>
  8. {% endfor %}

{% for key, val in data %} 标签可以获取到map的key值:

  1. {% for k, v in list %}
  2. <ul>
  3. <li>{{ v.name }}: This key is {{ k }}</li>
  4. </ul>
  5. {% endfor %}

系统不支持中断循环,如果你想这样,你可以改变你想遍历的变量来使得变量只包含你想遍历的值

类似的,系统也不支持continue语句

{% for %} 标签内置了一个forloop模板变量,这个变量含有一些属性可以提供给你一些关于循环的信息

1、forloop.Counter 表示循环的次数,它从1开始计数,第一次循环设为1,例如:

  1. {% for item in todo_list %}
  2. <p>{{ forloop.Counter }}: {{ item }}</p>
  3. {% endfor %}

2、forloop.Counter0 类似于 forloop.Counter,但它是从0开始计数,第一次循环设为0

3、forloop.Revcounter 表示循环中剩下的items数量,第一次循环时设为items总数,最后一次设为1

4、forloop.Revcounter0 类似于 forloop.Revcounter,但它是表示的数量少一个,即最后一次循环时设为0

5、forloop.First 当第一次循环时值为 true,在特别情况下很有用:

  1. {% for object in objects %}
  2. {% if forloop.First %}<li class="first">{% else %}<li>{% endif %}
  3. {{ object }}
  4. </li>
  5. {% endfor %}

6、forloop.Last 当最后一次循环时值为true

  1. {% for link in links %}{{ link }}{% if not forloop.Last %} | {% endif %}{% endfor %}

7、forloop.Parentloop 在嵌套循环中表示父循环的forloop:

  1. {% for country in countries %}
  2. <table>
  3. {% for city in country.city_list %}
  4. <tr>
  5. <td>Country #{{ forloop.Parentloop.Counter }} </td>
  6. <td>City #{{ forloop.Counter }}</td>
  7. <td>{{ city }}</td>
  8. </tr>
  9. {% endfor %}
  10. </table>
  11. {% endfor %}

富有魔性的 forloop 变量:

  • 在for标签作用域中被自动创建为临时变量
  • for标签内不要使用自定义的 forloop 变量,它会被自动创建的同名的临时变量覆盖
  • for标签之外,名称为 forloop 的变量仍然可用

6.2.3 ifequal/ifnotequal

模板系统并不是一个严格意义上的编程语言,所以它并不允许我们执行Go语句

然而在模板语言里比较两个值并且在他们一致的时候显示一些内容,确实是一个在常见不过的需求了——所以模版提供了ifequal标签。

{% ifequal %} 比较两个值,如果相等,则显示 {% ifequal %}和{% endifequal %} 之间的所有内容:

  1. {% ifequal user currentuser %}
  2. <h1>Welcome!</h1>
  3. {% endifequal %}

参数可以是硬编码的string,单引号和双引号均可,下面的代码是合法的:

  1. {% ifequal section 'sitenews' %}
  2. <h1>Site News</h1>
  3. {% endifequal %}
  4. {% ifequal section "community" %}
  5. <h1>Community</h1>
  6. {% endifequal %}

{% if %} 一样,{% ifequal %} 标签支持 {% else %}

  1. {% ifequal section 'sitenews' %}
  2. <h1>Site News</h1>
  3. {% else %}
  4. <h1>No News Here</h1>
  5. {% endifequal %}

其它的模板变量,strings,integers和小数都可以作为 {% ifequal %} 的参数:

  1. {% ifequal variable 1 %}
  2. {% ifequal variable 1.23 %}
  3. {% ifequal variable 'foo' %}
  4. {% ifequal variable "foo" %}

其它的Go类型,如数组、切片或布尔值不能硬编码在 {% ifequal %} 里面,下面是不合法的

  1. {% ifequal variable true %}
  2. {% ifequal variable [1, 2, 3,]%}
  3. {% ifequal variable {'key': 'value'} %

如果你需要判断某个变量是true或false,用 {% if %} 即可。

6.2.4 注释

和HTML或编程语言如Go一样,模板语言允许注释 {# #},如:

  1. {# This is a comment #}

模板渲染时注释不会输出,一个注释不能分成多行
下面的模板渲染时会和模板中的内容一样,注释标签不会解析成注释
This is a {# comment goes here
and spans another line #}
test.

6.2.5 过滤器

模板过滤器是变量显示前转换它们的值的方式,看起来像下面这样:

  1. {{ name|lower }}

这将显示通过 lower 过滤器过滤后 {{ name }} 变量的值,它将文本转换成小写

使用 | 管道来申请一个过滤器

过滤器可以串成链,即一个过滤器的结果可以传向下一个

下面是escape文本内容然后把换行转换成p标签的习惯用法:

  1. {{ my_text|escape|linebreaks }}

有些过滤器需要参数,需要参数的过滤器的样子:

  1. {{ bio|truncatechars:"30" }}

这将显示bio标量的前30个字,过滤器参数一直使用双引号

下面是一些最重要的过滤器:

1、addslashes 在任何 \'" 前添加一个 \,当你把一些文本输出到一个JavaScript字符串时这会十分有用。

2、date 根据一个格式化string参数来格式化 time.Time 对象,例如:

  1. {{ pub_date|date:"2006-01-02 15:04:05" }}

3、escape 避免给定的string里出现 &"'<>

当你处理用户提交的数据和确认合法的XML和XHTML数据时这将很有用

escape 将作如下的一些转换:

  1. Converts & to &amp;amp;
  2. Converts < to &amp;lt;
  3. Converts > to &amp;gt;
  4. Converts "(双引号) to &amp;quot;
  5. Converts '(单引号) to &amp;#39;

4、length 返回值的长度,你可以在一个list或string上做此操作,或者在任何知道怎样决定自己的长度的Go对象上做此操作。