Django 模板语言

您所在的位置:网站首页 Django模板继承格式是什么 Django 模板语言

Django 模板语言

2024-06-12 19:16| 来源: 网络整理| 查看: 265

Django模版语言¶

本文将介绍Django模版系统的语法。如果您需要更多该系统如何工作的技术细节,以及希望扩展它,请浏览 The Django template language: for Python programmers.

Django模版语言的设计致力于在性能和简单上取得平衡。 它的设计使习惯于使用HTML的人也能够自如应对。如果您有过使用其他模版语言的经验,像是 Smarty 或者 Jinja2, 那么您将对Django的模版语言感到一见如故。

理念

如果您有过编程背景,或者您使用过一些在HTML中直接混入程序代码的语言,那么现在您需要记住,Django的模版系统并不是简单的将Python嵌入到HTML中。 设计决定了:模版系统致力于表达外观,而不是程序逻辑。

Django的模版系统提供了和某些程序架构类似的标签——用于布尔判断的 if 标签, 用于循环的 for 标签等等。——但是这些都不是简单的作为Python代码那样来执行的,并且,模版系统也不会随意执行Python表达式。只有下面列表中的标签、过滤器和语法才是默认就被支持的。 (但是您也可以根据需要添加 您自己的扩展  到模版语言中)。

模版¶

模版是纯文本文件。它可以产生任何基于文本的的格式(HTML,XML,CSV等等)。

模版包括在使用时会被值替换掉的 变量,和控制模版逻辑的 标签。

下面是一个小模版,它说明了一些基本的元素。后面的文档中会解释每个元素。

{% extends "base_generic.html" %} {% block title %}{{ section.title }}{% endblock %} {% block content %} {{ section.title }} {% for story in story_list %} {{ story.headline|upper }}

{{ story.tease|truncatewords:"100" }}

{% endfor %} {% endblock %}

理念

为什么要使用基于文本的模版,而不是基于XML的(比如Zope的TAL)呢?我们希望Django的模版语言可以用在更多的地方,而不仅仅是XML/HTML模版。在线上世界,我们在email、Javascript和CSV中使用它。你可以在任何基于文本的格式中使用这个模版语言。

还有,让人类编辑XML简直是施虐狂的做法!

变量¶

变量看起来就像是这样: {{ variable }}。当模版引擎遇到一个变量,它将计算这个变量,然后用结果替换掉它本身。变量的命名包括任何字母数字以及下划线 ("_")的组合。点(".") 也在会变量部分中出现,不过它有特殊的含义,我们将在后面说明。重要的是, 你不能在变量名称中使用空格和标点符号。

点号(.)用来访问变量的属性。

幕后

从技术上来说,当模版系统遇到点("."),它将以这样的顺序查询:

字典查询(Dictionary lookup) 属性或方法查询(Attribute or method lookup) 数字索引查询(Numeric index lookup)

如果计算结果的值是可调用的,它将被无参数的调用。调用的结果将成为模版的值。

这个查询顺序,会在优先于字典查询的对象上造成意想不到的行为。例如,思考下面的代码片段,它尝试循环 collections.defaultdict:

{% for k, v in defaultdict.iteritems %} Do something with k and v here... {% endfor %}

因为字典查询首先发生,行为奏效了并且提供了一个默认值,而不是使用我们期望的 .iteritems() 方法。在这种情况下,考虑首先转换成字典。

在前文的例子中, {{ section.title }}将被替换为  section 对象的 title 属性。

如果你使用的变量不存在, 模版系统将插入 string_if_invalid 选项的值, 它被默认设置为'' (空字符串) 。

注意,像{{ foo.bar }} 这种模版表达式中的“bar”, 如果在模版上下文中存在,将解释为一个字面意义的字符串而不是使用变量“bar”的值 。

过滤器¶

您可以通过使用 过滤器来改变变量的显示。

过滤器看起来是这样的:{{ name|lower }}。这将在变量 {{ name }} 被过滤器 lower 过滤后再显示它的值,该过滤器将文本转换成小写。使用管道符号 (|)来应用过滤器。

过滤器能够被“串联”。一个过滤器的输出将被应用到下一个。{{ text|escape|linebreaks }} 就是一个常用的过滤器链,它编码文本内容,然后把行打破转成

标签。

一些过滤器带有参数。过滤器的参数看起来像是这样: {{ bio|truncatewords:30 }}。这将显示 bio 变量的前30个词。

过滤器参数包含空格的话,必须被引号包起来;例如,使用逗号和空格去连接一个列表中的元素,你需要使用 {{ list|join:", " }}。

Django提供了大约六十个内置的模版过滤器。你可以在 内置过滤器参考手册中阅读全部关于它们的信息。为了体验一下它们的作用,这里有一些常用的模版过滤器:

default

如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值。例如:

{{ value|default:"nothing" }}

如果 value没有被提供,或者为空, 上面的例子将显示“nothing”。

length

返回值的长度。它对字符串和列表都起作用。例如:

{{ value|length }}

如果 value 是 ['a', 'b', 'c', 'd'],那么输出是 4。

filesizeformat

将该数值格式化为一个 “人类可读的” 文件容量大小 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:

{{ value|filesizeformat }}

如果 value 是 123456789,输出将会是 117.7 MB。

再说一下,这仅仅是一些例子;查看 内置过滤器参考手册 来获取完整的列表。

您也可以创建自己的自定义模版过滤器;参考 自定义模版标签和过滤器。

更多

Django的admin接口提供了一个模板标记和可用的过滤器的完整参考。请参见The Django admin documentation generator。

标签¶

标签看起来像是这样的: {% tag %}。标签比变量复杂得多:有些用于在输出中创建文本,有些用于控制循环或逻辑,有些用于加载外部信息到模板中供以后的变量使用。

有些标签需要开始标签和结束标签(例如{% tag %} ... tag contents ... {% endtag %})。

Django自带了大约24个内置的模版标签。你可以在 内置标签参考手册中阅读全部关于它们的内容。为了体验一下它们的作用,这里有一些常用的标签:

for

循环数组中的每个元素。例如,显示 athlete_list中提供的运动员列表:

{% for athlete in athlete_list %} {{ athlete.name }} {% endfor %} if, elif, and else

计算一个变量,并且当变量是“true”时,显示块中的内容:

{% 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 }} 的输出。否则, 如果 athlete_in_locker_room_list 不为空, 将显示 “Athletes should be out...” 这个消息。如果两个列表都是空的,将显示 “No athletes.” 。

您也可以在if 标签中使用过滤器和多种运算符:

{% if athlete_list|length > 1 %} Team: {% for athlete in athlete_list %} ... {% endfor %} {% else %} Athlete: {{ athlete_list.0.name }} {% endif %}

当上面的例子工作时,需要注意,大多数模版过滤器返回字符串,所以使用过滤器做数学的比较通常都不会像您期望的那样工作。length 是一个例外。

block and extends 参见模板继承(下文),一种减少模板样板文件的有效方法。

再说一下,上面的仅仅是整个列表的一部分;查看 内置标签参考手册 来获取完整的列表。

您也可以创建您自己的自定义模版标签;参考 自定义模版标签和过滤器。

更多

Django的管理界面可以包含对给定网站可用的所有模板标记和过滤器的完整引用。请参见The Django admin documentation generator。

注释¶

要注释模版中一行的部分内容,使用注释语法 {# #}.

例如,这个模版将被渲染为 'hello':

{# greeting #}hello

注释可以包含任何模版代码,有效的或者无效的都可以。例如:

{# {% if foo %}bar{% else %} #}

这个语法只能被用于单行注释 (在 {# 和 #} 分隔符中,不允许有新行)。如果你需要注释掉模版中的多行内容,请查看 comment 标签。

模版继承¶

Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可以让您创建一个基本的“骨架”模版,它包含您站点中的全部元素,并且可以定义能够被子模版覆盖的 blocks 。

通过从下面这个例子开始,可以容易的理解模版继承:

{% block title %}My amazing site{%/span> endblock %} {% block sidebar %} Home Blog {% endblock %} {% block content %}{% endblock %}

这个模版,我们把它叫作 base.html, 它定义了一个可以用于两列排版页面的简单HTML骨架。“子模版”的工作是用它们的内容填充空的blocks。

在这个例子中, block 标签定义了三个可以被子模版内容填充的block。 block 告诉模版引擎: 子模版可能会覆盖掉模版中的这些位置。

子模版可能看起来是这样的:

{% extends "base.html" %}/span> {% block title %}My amazing blog{% endblock %} {% block content %} {% for entry in blog_entries %} {{ entry.title }}

{{ entry.body }}

{% endfor %} {% endblock %}

extends 标签是这里的关键。它告诉模版引擎,这个模版“继承”了另一个模版。当模版系统处理这个模版时,首先,它将定位父模版——在此例中,就是“base.html”。

那时,模版引擎将注意到 base.html 中的三个 block 标签,并用子模版中的内容来替换这些block。根据 blog_entries 的值,输出可能看起来是这样的:

My amazing blog Home Blog Entry one

This is my first entry.

Entry two

This is my second entry.

请注意,子模版并没有定义 sidebar block,所以系统使用了父模版中的值。父模版的 {% block %} 标签中的内容总是被用作备选内容(fallback)。

您可以根据需要使用多级继承。使用继承的一个常用方式是类似下面的三级结构:

创建一个 base.html 模版来控制您整个站点的主要视觉和体验。 为您的站点的每一个“分支”创建一个base_SECTIONNAME.html 模版。例如, base_news.html, base_sports.html。这些模版都继承自 base.html ,并且包含了每部分特有的样式和设计。 为每一种页面类型创建独立的模版,例如新闻内容或者博客文章。这些模版继承对应分支的模版。

这种方式使代码得到最大程度的复用,并且使得添加内容到共享的内容区域更加简单,例如分支范围内的导航。

这里是使用继承的一些提示:

如果你在模版中使用 {% extends %} 标签,它必须是模版中的第一个标签。其他的任何情况下,模版继承都将无法工作。

在base模版中设置越多的 {% block %} 标签越好。请记住,子模版不必定义全部父模版中的blocks,所以,你可以在大多数blocks中填充合理的默认内容,然后,只定义你需要的那一个。多一点钩子总比少一点好。

如果你发现你自己在大量的模版中复制内容,那可能意味着你应该把内容移动到父模版中的一个 {% block %} 中。

如果需要获取父模板中的block 的内容,可以使用{{ block.super }} 变量。如果你想要在父block 中新增内容而不是完全覆盖它,它将非常有用。使用{{ block.super }} 插入的数据不会被自动转义(参见下一节),因为父模板中的内容已经被转义。

为了更好的可读性,你也可以给你的 {% endblock %} 标签一个 名字 。例如:

{% block content %} ... {% endblock content %}

在大型模版中,这个方法帮你清楚的看到哪一个  {% block %} 标签被关闭了。

最后,请注意不能在一个模版中定义多个相同名字的block 标签。这个限制的存在是因为block标签的作用是“双向”的。这个意思是,block 标签不仅提供了一个坑去填,它定义向父模版的坑中所填的内容。如果在一个模版中有两个名字一样的 block 标签,模版的父模版将不知道使用哪个block的内容。

自动HTML转义¶

当从模版中生成HTML时,总会有这样一个风险:值可能会包含影响HTML最终呈现的字符。例如,思考这个模版片段:

Hello, {{ name }}

首先,它看起来像是一个无害的方式来显示用户的名字,但是设想一下,如果用户像下面这样输入他的名字,会发生什么:

alert('hello')

使用这个名字值,模版将会被渲染成这样:

Hello, alert('hello')

...这意味着,浏览器将会弹出一个Javascript警示框!

类似的,如果名字包含一个 '



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3