第三章:模版层 - 2:Django内置模板标签

Django内置标签总览

可以查询下表来总览Django的内置标签:

标签 说明
autoescape 自动转义开关
block 块引用
comment 注释
csrf_token CSRF令牌
cycle 循环对象的值
debug 调试模式
extends 继承模版
filter 过滤功能
firstof 输出第一个不为False的参数
for 循环对象
for … empty 带empty说明的循环
if 条件判断
ifequal 如果等于
ifnotequal 如果不等于
ifchanged 如果有变化,则..
include 导入子模版的内容
load 加载标签和过滤器
lorem 生成无用的废话
now 当前时间
regroup 根据对象重组集合
resetcycle 重置循环
spaceless 去除空白
templatetag 转义模版标签符号
url 获取url字符串
verbatim 禁用模版引擎
widthratio 宽度比例
with 上下文变量管理器

1. autoescape

控制自动转义是否可用。参数是on或off。 该标签会以一个endautoescape作为结束标签.

例如:

{% autoescape on %}
    {{ body }}
{% endautoescape %}

2. block

block标签可以被子模板覆盖。

3. comment

{% comment %}{% endcomment %}之间的内容会被忽略,作为注释。

比如,当要注释掉一些代码时,可以用此来记录代码被注释掉的原因。

例如:

<p>Rendered text with {{ pub_date|date:"c" }}</p>
{% comment "Optional note" %}
    <p>Commented out text with {{ create_date|date:"c" }}</p>
{% endcomment %}

comment标签不能嵌套使用。

4. csrf_token

这个标签用于跨站请求伪造保护。常用于为form表单提供csrf令牌。

5. cycle

每当这个标签被访问,返回它的下一个元素。第一次访问返回第一个元素,第二次访问返回第二个参数,以此类推. 一旦所有的变量都被访问过了,就会回到最开始的地方,重复下去。这个标签在循环中特别有用:

{% for o in some_list %}
    <tr class="{% cycle 'row1' 'row2'%}">
        ...
    </tr>
{% endfor %}

第一次迭代产生的HTML引用了row1类,第二次则是row2类,第三次又是row1 类,如此类推。

cycle的本质是根据某个规律,提供某种特性,比如想循环给表格的行添加底色等等。

也可以使用变量, 例如,如果你有两个模版变量:rowvalue1和rowvalue2, 可以让他们的值像这样替换:

{% for o in some_list %}
    <tr class="{% cycle rowvalue1 rowvalue2 %}">
        ...
    </tr>
{% endfor %}

被包含在cycle中的变量将会被转义。 可以禁止自动转义:

{% for o in some_list %}
    <tr class="{% autoescape off %}{% cycle rowvalue1 rowvalue2 %}{% endautoescape %}">
        ...
    </tr>
{% endfor %}

可以混合使用变量和字符串:

{% for o in some_list %}
    <tr class="{% cycle 'row1' rowvalue2 'row3' %}">
        ...
    </tr>
{% endfor %}

在某些情况下,可能需要连续引用一个当前循环的值,而不前进到下一个循环值。要达到这个目的,只需使用as来给{% cycle %}取一个别名,就像这样:

{% cycle 'row1' 'row2' as rowcolors %}

从那时起(设置别名后),你可以将别名当作一个模板变量进行引用,从而随意在模板中插入当前循环的值。 如果要将循环值移动到原始cycle标记的下一个值,可以使用另一个cycle标记并指定变量的名称。看下面的例子:

<tr>
    <td class="{% cycle 'row1' 'row2' as rowcolors %}">...</td>
    <td class="{{ rowcolors }}">...</td>
</tr>
<tr>
    <td class="{% cycle rowcolors %}">...</td>
    <td class="{{ rowcolors }}">...</td>
</tr>

将输出:

<tr>
    <td class="row1">...</td>
    <td class="row1">...</td>
</tr>
<tr>
    <td class="row2">...</td>
    <td class="row2">...</td>
</tr>

cycle 标签中,通过空格分割,可以使用任意数量的值。被包含在单引号(')或者双引号(")中的值被认为是可迭代字符串,相反,没有被引号包围的值被当作模版变量。

6. debug

输出整个调试信息,包括当前上下文和导入的模块。

7. extends

表示当前模板继承自一个父模板。

这个标签可以有两种用法:

  • {% extends "base.html" %}:继承名为"base.html"的父模板
  • {% extends variable %}:使用variable变量表示的模版

Django1.10中添加了使用相对路径的能力。通常模板名称是相对于模板加载器的根目录。字符串参数也可以是以./../开头的相对路径。 例如,假设有以下目录结构:

dir1/
    template.html
    base2.html
    my/
        base3.html
base1.html

在template.html中,以下路径将有效:

{% extends "./base2.html" %}
{% extends "../base1.html" %}
{% extends "./my/base3.html" %}

8. filter

通过一个或多个过滤器对内容过滤。需要结束标签endfilter。

例如:

{% filter force_escape|lower %}
    This text will be HTML-escaped, and will appear in all lowercase.
{% endfilter %}

9. firstof

输出第一个不为False参数。 如果传入的所有变量都为False,就什么也不输出。

例如:

{% firstof var1 var2 var3 %}

它等价于:

{% if var1 %}
    {{ var1 }}
{% elif var2 %}
    {{ var2 }}
{% elif var3 %}
    {{ var3 }}
{% endif %}

当然也可以用一个默认字符串作为输出以防止传入的所有变量都是False:

{% firstof var1 var2 var3 "fallback value" %}

10. for

循环对象中的每一个元素

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

可以使用{% for obj in list reversed %}进行反向循环。

如果循环对象points的每个元素都是(x,y)这样的二元元组,可以像以下面一样输出:

{% for x, y in points %}
    There is a point at {{ x }},{{ y }}
{% endfor %}

如果你想访问一个字典中的键值,这个方法同样有用:

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

请记住,对于点运算符,字典键查找优先于方法查找。

下面是Django为for标签内置的一些属性,可以当作变量一样使用{{ }}在模版中使用。

  • forloop.counter:循环的当前索引值,从1开始计数;常用于生成一个表格或者列表的序号!
  • forloop.counter0:循环的当前索引值,从0开始计数;
  • forloop.revcounter: 循环结束的次数(从1开始)
  • forloop.revcounter0 循环结束的次数(从0开始)
  • forloop.first:判断当前是否循环的第一次,是的话,该变量的值为True。我们经常要为第一行加点特殊的对待,就用得上这个判断了,结合if。
  • forloop.last:如果这是最后一次循环,则为真
  • forloop.parentloop:对于嵌套循环,返回父循环所在的循环次数。某些场景下,这是个大杀器,能解决你很多头疼的问题。

11. for ... empty

for标签带有一个可选的{% empty %}从句,以便在循环对象是空的或者没有被找到时,可以有所操作和提示。

<ul>
{% for athlete in athlete_list %}
    <li>{{ athlete.name }}</li>
{% empty %}
    <li>Sorry, no athletes in this list.</li>
{% endfor %}
</ul>

它和下面的例子作用相等,但是更简洁、更清晰甚至可能运行起来更快:

<ul>
  {% if athlete_list %}
    {% for athlete in athlete_list %}
      <li>{{ athlete.name }}</li>
    {% endfor %}
  {% else %}
    <li>Sorry, no athletes in this list.</li>
  {% endif %}
</ul>

12. if

{% if %}会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的False值),这个内容块就会输出:

{% 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 }}过滤器展示出athletes的数量。

if标签之后可以带有一个或者多个{% elif %}从句,也可以带有一个{% else %}从句以便在之前的所有条件不成立的情况下完成执行。这些从句都是可选的。

布尔运算符:

if标签可以使用not,and或or来测试布尔值:

{% 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子句,and的优先级高于or :

{% if athlete_list and coach_list or cheerleader_list %}

将解释如下:

if (athlete_list and coach_list) or cheerleader_list

在if标签中使用实际括号是错误的语法,这点不同于Python。如果需要为它们指示优先级,应使用嵌套的if标签。

if标签允许使用这些操作符:==, !=, <, >, <=, >=, in, not in, is, is not,如下面的列子所示:

{% if somevar == "x" %}
  This appears if variable somevar equals the string "x"
{% endif %}

{% if somevar != "x" %}
  This appears if variable somevar does not equal the string "x",
  or if somevar is not found in the context
{% endif %}

{% if somevar < 100 %}
  This appears if variable somevar is less than 100.
{% endif %}

{% if somevar > 0 %}
  This appears if variable somevar is greater than 0.
{% endif %}

{% if somevar <= 100 %}
  This appears if variable somevar is less than 100 or equal to 100.
{% endif %}

{% if somevar >= 1 %}
  This appears if variable somevar is greater than 1 or equal to 1.
{% endif %}

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

{% if "hello" in greetings %}
  If greetings is a list or set, one element of which is the string
  "hello", this will appear.
{% endif %}

{% if user not in users %}
  If users is a QuerySet, this will appear if user is not an
  instance that belongs to the QuerySet.
{% endif %}

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

{% if somevar is None %}
  This appears if somevar is None, or if somevar is not found in the context.
{% endif %}

{% if somevar is not True %}
  This appears if somevar is not True, or if somevar is not found in the
  context.
{% endif %}

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

也可以在if表达式中使用过滤器。 像这样:

{% if messages|length >= 100 %}
   You have lots of messages today!
{% endif %}

所有上述操作符都可以组合以形成复杂表达式。对于这样的表达式,重要的是优先级规则。操作符的优先级从低至高如下:

or
and
not
in
==,!=,<,>,<= ,>=

与Python的规则是一样的。 所以,对于下面的复杂if标签:

{% if a == b or c == d and e %}

将被解释为:

(a == b) or ((c == d) and e)

如果想要不同的优先级,那么你需要使用嵌套的if标签,而不能使用圆括号。

比较运算符不能像Python或数学符号中那样“链接”。 例如,不能使用:

{% if a > b > c %}  (错误的用法)

应该使用:

{% if a > b and b > c %}

13. ifequal和ifnotequal

{% ifequal a b %} ... {% endifequal %}是一种过时的写法,等同于{% if a == b %} ... {% endif %}。 同样, {% ifnotequal a b %} ... {% endifnotequal %}等同于{% if a != b %} ... {% endif %}。这两个标签将在以后的版本中弃用。

14. ifchanged

检查一个值是否在上一次的迭代中被改变了。

{% ifchanged %}标签通常用在循环里。它有两个用处:

检查已经渲染过的内容的当前状态。并且只会显示发生改变的内容。例如,以下的代码是输出days的列表项,不过它只会输出被修改过月份的项:

<h1>Archive for {{ year }}</h1>

{% for date in days %}
    {% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %}
    <a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
{% endfor %}

如果标签内有多个值时,则会比较每一个值是否与上一次不同。例如,以下显示每次更改时的日期,如果小时或日期已更改,则显示小时:

{% for date in days %}
    {% ifchanged date.date %} {{ date.date }} {% endifchanged %}
    {% ifchanged date.hour date.date %}
        {{ date.hour }}
    {% endifchanged %}
{% endfor %}

ifchanged标记也可以采用可选的{% else %}将显示值没有改变的情况:

{% for match in matches %}
    <div style="background-color:
        {% ifchanged match.ballot_id %}
            {% cycle "red" "blue" %}
        {% else %}
            gray
        {% endifchanged %}
    ">{{ match }}</div>
{% endfor %}

15. include

加载指定的模板并以标签内的参数渲染。这是一种引入别的模板的方法,一定要将include和extend区分开!include类似Python的import。

{% include "foo/bar.html" %}

也可以使用变量名template_name

{% include template_name %}

下面这个示例生成输出“Hello, John!”:

context:变量greeting="Hello",变量person="John"。

模板:

{% include "name_snippet.html" %}

name_snippet.html模板:

{{ greeting }}, {{ person|default:"friend" }}!

可以使用关键字参数将额外的上下文传递到模板:

{% include "name_snippet.html" with person="Jane" greeting="Hello" %}

如果仅使用提供的变量来渲染上下文,添加only选项。

{% include "name_snippet.html" with greeting="Hi" only %}

include标签应该被理解为是一种"将子模版渲染并嵌入当前HTML中"的变种方法,而不应该看作是"解析子模版并在被父模版包含的情况下展现其被父模版定义的内容"。这意味着在不同的被包含的子模版之间并不共享父模版的状态,每一个子包含都是完全独立的渲染过程。

16. load

加载自定义模板标签。

下面的模板将会从somelibrary和package包中的otherlibrary中载入所有已经注册的标签和过滤器:

{% load somelibrary package.otherlibrary %}

还可以使用from参数从库中选择性加载单个过滤器或标记。

{% load foo bar from somelibrary %}

17. lorem

这个标签是用来在模版中提供文字样本以供测试用的。使用场景是什么?

比如你要写个demo,里面要有一大段的文字和篇章,你不可能真的去写一篇文章吧?如果懒得去网上COPY,又不愿意使用一堆毫无意义杂乱的乱码,那么使用这个方法,可以帮你自动填充一些可以阅读的内容。

PS:Django考虑得真细.....

用法:

{% lorem [count] [method] [random] %}

可以使用零个,一个,两个或三个参数。 这些参数是:

  • count :一个数字(或变量),其中包含要生成的段落或字数(默认值为1)。
  • method:HTML中使用p标签、还是w标签、还是b标签,决定文本格式。默认是“b”。
  • random:如果给出的话,random这个词在生成文本时不会使用公共段落。 例子:
{% lorem %}将输出常见的“lorem ipsum”段落。
{% lorem 3 p %}输出常用的“lorem ipsum”段落和两个随机段落,每段包裹在HTML`<p>`标签中。
{% lorem 2 w random %}将输出两个随机拉丁字。

18. now

显示当前的日期或时间。可以指定显示的格式。 例如:

It is {% now "jS F Y H:i" %}

下面的例子中,“o”和“f”都被反斜杠转义:

It is the {% now "jS \o\f F" %}

这将显示为“It is the 4th of September”。

还可以使用语法{% now “Y” as current_year %}将输出存储在变量中。

{% now "Y" as current_year %}
{% blocktrans %}Copyright {{ current_year }}{% endblocktrans %}

19. regroup

用对象间共有的属性重组列表。

对于下面的数据:

cities = [
    {'name': 'Mumbai', 'population': '19,000,000', 'country': 'India'},
    {'name': 'Calcutta', 'population': '15,000,000', 'country': 'India'},
    {'name': 'New York', 'population': '20,000,000', 'country': 'USA'},
    {'name': 'Chicago', 'population': '7,000,000', 'country': 'USA'},
    {'name': 'Tokyo', 'population': '33,000,000', 'country': 'Japan'},
]

如果你想显示按国家/地区排序的分层列表,如下所示:

India
    Mumbai: 19,000,000
    Calcutta: 15,000,000
USA
    New York: 20,000,000
    Chicago: 7,000,000
Japan
    Tokyo: 33,000,000

可以使用{% regroup %}标签来给每个国家的城市分组:

{% regroup cities by country as country_list %}

<ul>
{% for country in country_list %}
    <li>{{ country.grouper }}
    <ul>
        {% for city in country.list %}
          <li>{{ city.name }}: {{ city.population }}</li>
        {% endfor %}
    </ul>
    </li>
{% endfor %}
</ul>

让我们来看看这个例子。{% regroup %}有三个参数: 要重组的列表、用来分组的属性、结果列表的名字。在这里,我们通过country属性重新分组cities列表,并将结果保存在country_list中。

country_list的每个元素是具有两个字段的namedtuple()的实例:

  • grouper - 分组的项目(例如,字符串“India”或“Japan”)。
  • list - 此群组中所有项目的列表(例如,所有城市的列表,其中country ='India')。

20. resetcycle

Django1.11中的新功能。

重置先前的循环,以便在下一次循环时从其第一个项目重新启动。如果没有参数,{% resetcycle %}将重置最后一个{% cycle %}

用法示例:

{% for coach in coach_list %}
    <h1>{{ coach.name }}</h1>
    {% for athlete in coach.athlete_set.all %}
        <p class="{% cycle 'odd' 'even' %}">{{ athlete.name }}</p>
    {% endfor %}
    {% resetcycle %}
{% endfor %}

这个示例将返回下面的HTML:

<h1>José Mourinho</h1>
<p class="odd">Thibaut Courtois</p>
<p class="even">John Terry</p>
<p class="odd">Eden Hazard</p>

<h1>Carlo Ancelotti</h1>
<p class="odd">Manuel Neuer</p>
<p class="even">Thomas Müller</p>

注意第一个块以class="odd"结束,新的以class="odd"开头。没有{% resetcycle %}标签,第二个块将以class="even"开始。

还可以重置循环标签:

{% for item in list %}
    <p class="{% cycle 'odd' 'even' as stripe %} {% cycle 'major' 'minor' 'minor' 'minor' 'minor' as tick %}">
        {{ item.data }}
    </p>
    {% ifchanged item.category %}
        <h1>{{ item.category }}</h1>
        {% if not forloop.first %}{% resetcycle tick %}{% endif %}
    {% endifchanged %}
{% endfor %}

在这个例子中,我们有交替的奇数/偶数行和每五行出现一次的‘major’行。当类别更改时,只有五行周期被重置。

21. spaceless

删除HTML标签之间的空白,包括制表符和换行。

用法示例:

{% spaceless %}
    <p>
        <a href="foo/">Foo</a>
    </p>
{% endspaceless %}

这个示例将返回下面的HTML:

<p><a href="foo/">Foo</a></p>

仅会删除tags之间的空格,不会删除标签和文本之间的。下面的例子中,Hello周围的空格不会被删除:

{% spaceless %}
    <strong>
        Hello
    </strong>
{% endspaceless %}

22. templatetag

输出用于构成模板标签的语法字符。

由于模板系统没有“转义”的概念,无法在HTML中使用‘\’转义出类似{%的字符。为了显示模板标签本身,必须使用{% templatetag %}标签,并添加相应的参数:

  • openblock:{%
  • closeblock: %}
  • openvariable: {{
  • closevariable: }}
  • openbrace :{
  • closebrace: }
  • opencomment: {#
  • closecomment: #}

例如:

{% templatetag openblock %} url 'entry_list' {% templatetag closeblock %}

23. url

返回与给定视图和可选参数匹配的绝对路径引用(不带域名的URL)。在解析后返回的结果路径字符串中,每个特殊字符将使用iri_to_uri()编码。这可以避免在模板中硬编码超级链接路径。

{% url 'some-url-name' v1 v2 %}

第一个参数是url()的名字。 它可以是一个被引号引起来的字符串或者其他的上下文变量。其他参数是可选的并且以空格隔开,这些值会在URL中以参数的形式传递。上面的例子展示了如何传递位置参数,当然也可以使用关键字参数。

{% url 'some-url-name' arg1=v1 arg2=v2 %}

不要把位置参数和关键字参数混在一起使用。URLconf所需的所有参数都应该提供。

例如,假设有一个视图app_views.client,其URLconf接受客户端ID,并如下所示:

('^client/([0-9]+)/$', app_views.client, name='app-views-client')

如果你的应用中的URLconf已经被包含到项目URLconf中,比如下面这样

('^clients/', include('project_name.app_name.urls'))

然后,在模板中,你可以创建一个此视图的链接,如下所示:

{% url 'app-views-client' client.id %}

模板标签会输出字符串:/clients/client/123/

如果希望在不显示网址的情况下检索网址,可以使用略有不同的调用:

{% url 'some-url-name' arg arg2 as the_url %}
<a href="{{ the_url }}">I'm linking to {{ the_url }}</a>

如果视图不存在,{% url ... as var %}语法不会导致错误。

{% url 'some-url-name' as the_url %}
{% if the_url %}
  <a href="{{ the_url }}">Link to optional stuff</a>
{% endif %}

如果使用urlconf的名称空间网址,通过冒号指定完全名称,如下所示:

{% url 'myapp:view-name' %}

再次强调,是冒号,不是圆点不是斜杠!

24. verbatim

禁止模版引擎在该标签中进行渲染工作。

常见的用法是允许与Django语法冲突的JavaScript模板图层工作。 像这样:

{% verbatim %}
    {{if dying}}Still alive.{{/if}}
{% endverbatim %}

25. widthratio

为了创建柱状形图,此标签计算给定值与最大值的比率,然后将该比率应用于常量。

像这样:

<img src="bar.png" alt="Bar"
     height="10" width="{% widthratio this_value max_value max_width %}" />

如果this_value是175,max_value是200,并且max_width是100,则上述示例中的图像将是88像素宽(因为175 / 200 = .875; .875 * 100 = 87.5,四舍五入入为88)。

26. with

使用一个简单地名字缓存一个复杂的变量,当你需要使用一个代价较大的方法(比如访问数据库)很多次的时候这是非常有用的。

像这样:

{% with total=business.employees.count %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

total只在with标签内部有效。

可以分配多个变量:

{% with alpha=1 beta=2 %}
    ...
{% endwith %}
posted @ 2020-05-06 10:20  哈喽哈喽111111  阅读(244)  评论(0编辑  收藏  举报