Python Django基础教程(二)(模板templatetags)

释放双眼,带上耳机,听听看~!

Django版本:1.11
操作系统:Windows
欢迎加入学习交流QQ群:657341423


模板的使用:
模板是一个文本,用于分离文档的表现形式和内容。 模板定义了占位符以及各种用于规范文档该如何显示的各部分基本逻辑(模板标签)。 模板通常用于产生HTML,但是Django的模板也能产生任何基于文本格式的文档。
模版大致结构:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1<html>
2<head><title>Ordering notice</title></head>
3<body>
4<h1>Ordering notice</h1>
5<p>Dear {{ person_name }},</p>
6<p>Thanks for placing an order from {{ company }}. It's scheduled to
7ship on {{ ship_date|date:"F j, Y" }}.</p>
8<p>Here are the items you've ordered:</p>
9<ul>
10{% for item in item_list %}
11    <li>{{ item }}</li>
12{% endfor %}
13</ul>
14{% if ordered_warranty %}
15    <p>Your warranty information will be included in the packaging.</p>
16{% else %}
17    <p>You didn't order a warranty, so you're on your own when
18    the products inevitably stop working.</p>
19{% endif %}
20<p>Sincerely,<br />{{ company }}</p>
21</body>
22</html>
23
24

用两个大括号括起来的文字(例如 {{ person_name }} )称为 变量(variable) 。这意味着在此处插入指定变量的值。

被大括号和百分号包围的文本(例如 {% if ordered_warranty %} )是 模板标签(template tag) 。标签(tag)定义比较明确,即: 仅通知模板系统完成某些工作的标签。

这个例子中的模板包含一个for标签( {% for item in item_list %} )和一个if 标签({% if ordered_warranty %} )

for标签类似Python的for语句,可让你循环访问序列里的每一个项目。 if 标签,正如你所料,是用来执行逻辑判断的。 在这里,tag标签检查ordered_warranty值是否为True。如果是,模板系统将显示{% if ordered_warranty %}和{% else %}之间的内容;否则将显示{% else %}和{% endif %}之间的内容。{% else %}是可选的。

就是通俗一点说, {{xxx}}这个为变量。{% %} 为语法使用。在整体上模版的结构就是如此。

了解到模版的大致结构,再了解一下模版标签


if/else
只能判断True 和False
{% if %} 标签检查(evaluate)一个变量,如果这个变量为真(即,变量存在,非空,不是布尔值假),系统会显示在 {% if %} 和 {% endif %} 之间的任何内容,例如:


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

{% else %} 标签是可选的:


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

{% if %} 标签接受 and , or 或者 not 关键字来对多个变量做判断 ,或者对变量取反( not ),但不允许在同一个标签中同时使用 and 和 or ,因为逻辑上可能模糊的。


for


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

给标签增加一个 reversed 使得该列表被反向迭代:


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

可以嵌套使用 {% for %} 标签

在执行循环之前先检测列表的大小是一个通常的做法,当列表为空时输出一些特别的提示。


1
2
3
4
5
6
7
8
9
1{% if athlete_list %}
2    {% for athlete in athlete_list %}
3        <p>{{ athlete.name }}</p>
4    {% endfor %}
5{% else %}
6    <p>There are no athletes. Only computer programmers.</p>
7{% endif %}
8
9

因为这种做法十分常见,所以for 标签支持一个可选的{% empty %} 分句,通过它我们可以定义当列表为空时的输出内容 下面的例子与之前那个等价:


1
2
3
4
5
6
7
1{% for athlete in athlete_list %}
2    <p>{{ athlete.name }}</p>
3{% empty %}
4    <p>There are no athletes. Only computer programmers.</p>
5{% endfor %}
6
7

在每个{% for %}循环里有一个称为forloop 的模板变量
forloop.counter 总是一个表示当前循环的执行次数的整数计数器。 这个计数器是从1开始的,所以在第一次循环时 forloop.counter 将会被设置为1。
forloop.counter0 类似于 forloop.counter ,但是它是从0计数的。 第一次执行循环时这个变量会被设置为0。6
forloop.revcounter 是表示循环中剩余项的整型变量。 在循环初次执行时 forloop.revcounter 将被设置为序列中项的总数。 最后一次循环执行中,这个变量将被置1。
forloop.revcounter0 类似于 forloop.revcounter ,但它以0做为结束索引。 在第一次执行循环时,该变量会被置为序列的项的个数减1。
forloop.first 是一个布尔值,如果该迭代是第一次执行,那么它被置为

1
1` ```` ` ```` ` ```` `

在下面的情形中这个变量是很有用的
forloop.last 是一个布尔值;在最后一次执行循环时被置为True。
forloop.parentloop 是一个指向当前循环的上一级循环的 forloop 对象的引用(在嵌套循环的情况下)。 例子在此:


1
2
3
4
5
6
7
8
9
10
11
12
13
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 %}
12
13

forloop 变量仅仅能够在循环中使用。 在模板解析器碰到{% endfor %}标签后,forloop就不可访问了。


ifequal/ifnotequal
对比两个值是否相对,ifequal相等,ifnotequal不相等。只有模板变量,字符串,整数和小数可以作为 {% ifequal %} 标签的参数。其他任何类型,例如Python的字典类型、列表类型、布尔类型,不能用在 {% ifequal %} 中。
下面的例子比较两个模板变量 user 和 currentuser :


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

参数可以是硬编码的字符串,随便用单引号或者双引号引起来,所以下列代码都是正确的:


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

和 {% if %} 类似, {% ifequal %} 支持可选的 {% else%} 标签


注释
就像HTML或者Python,Django模板语言同样提供代码注释。 注释使用 {# #} :


1
2
3
1{# This is a comment #}
2
3

如果要实现多行注释,可以使用{% comment %} 模板标签,就像这样:


1
2
3
4
5
6
1{% comment %}
2This is a
3multi-line comment.
4{% endcomment %}
5
6

模板过滤器是在变量被显示前修改它的值的一个简单方法。 过滤器使用管道字符,如下所示:


1
2
3
1{{ name|lower }}
2
3

显示的内容是变量 {{ name }} 被过滤器 lower 处理后的结果,它功能是转换文本为小写
具体过滤器方法可以网上找一下资料。


include 模板标签
内建模板标签:该标签允许在(模板中)包含其它的模板的内容。就是html里面的iframe
下面这两个例子都包含了 nav.html 模板。这两个例子是等价的,它们证明单/双引号都是允许的。


1
2
3
4
1{% include 'nav.html' %}
2{% include "nav.html" %}
3
4

下面的例子包含了 includes/nav.html 模板的内容:


1
2
3
1{% include 'includes/nav.html' %}
2
3

下面的例子包含了以变量 template_name 的值为名称的模板内容:


1
2
3
1{% include template_name %}
2
3

模板继承
本质上来说,模板继承就是先构造一个基础框架模板,而后在其子模板中对它所包含站点公用部分和定义块进行重载。
就是说,比如每个网页都包含<HTML></HTML> 等重复的代码
第一步是定义 基础模板 , 该框架之后将由 子模板 所继承。 以下是我们目前所讲述范例的基础模板


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot;&gt;
2&lt;html lang=&quot;en&quot;&gt;
3&lt;head&gt;
4    &lt;title&gt;{% block title %}{% endblock %}&lt;/title&gt;
5&lt;/head&gt;
6&lt;body&gt;
7    &lt;h1&gt;My helpful timestamp site&lt;/h1&gt;
8    {% block content %}{% endblock %}
9    {% block footer %}
10    &lt;hr&gt;
11    &lt;p&gt;Thanks for visiting my site.&lt;/p&gt;
12    {% endblock %}
13&lt;/body&gt;
14&lt;/html&gt;
15
16

这个叫做 base.html 的模板定义了一个简单的 HTML 框架文档,我们将在本站点的所有页面中使用。 子模板的作用就是重载、添加或保留那些块的内容。
我们使用一个以前已经见过的模板标签: {% block %} 。 所有的 {% block %} 标签告诉模板引擎,子模板可以重载这些部分。 每个{% block %}标签所要做的是告诉模板引擎,该模板下的这一块内容将有可能被子模板覆盖。
现在我们已经有了一个基本模板,我们可以修改 current_datetime.html 模板来 使用它。


1
2
3
4
5
6
7
8
1{% extends &quot;base.html&quot; %}
2
3{% block title %}The current time{% endblock %}
4{% block content %}
5&lt;p&gt;It is now {{ current_date }}.&lt;/p&gt;
6{% endblock %}
7
8

模板引擎发现了 {% extends %} 标签, 注意到该模板是一个子模板。 模板引擎立即装载其父模板,即本例中的 base.html 。
模板引擎注意到 base.html 中的三个 {% block %} 标签,并用子模板的内容替换这些 block 。因此,引擎将会使用我们在 { block title %} 中定义的标题,对 {% block content %} 也是如此。 所以,网页标题一块将由 {% block title %}替换,同样地,网页的内容一块将由 {% block content %}替换。
注意由于子模板并没有定义 footer 块,模板系统将使用在父模板中定义的值。 父模板 {% block %} 标签中的内容总是被当作一条退路。


使用继承的一种常见方式是下面的三层法:

创建 base.html 模板,在其中定义站点的主要外观感受。 这些都是不常修改甚至从不修改的部分。

为网站的每个区域创建 base_SECTION.html 模板(例如, base_photos.html 和 base_forum.html )。这些模板对 base.html 进行拓展,并包含区域特定的风格与设计。

为每种类型的页面创建独立的模板,例如论坛页面或者图片库。 这些模板拓展相应的区域模板。

这个方法可最大限度地重用代码,并使得向公共区域(如区域级的导航)添加内容成为一件轻松的工作。


以下是使用模板继承的一些诀窍:

如果在模板中使用 {% extends %} ,必须保证其为模板中的第一个模板标记。 否则,模板继承将不起作用。

一般来说,基础模板中的 {% block %} 标签越多越好。 记住,子模板不必定义父模板中所有的代码块,因此你可以用合理的缺省值对一些代码块进行填充,然后只对子模板所需的代码块进行(重)定义。 俗话说,钩子越多越好。

如果发觉自己在多个模板之间拷贝代码,你应该考虑将该代码段放置到父模板的某个 {% block %} 中。

如果你需要访问父模板中的块的内容,使用 {{ block.super }}这个标签吧,这一个魔法变量将会表现出父模板中的内容。 如果只想在上级代码块基础上添加内容,而不是全部重载,该变量就显得非常有用了。

不允许在同一个模板中定义多个同名的 {% block %} 。 存在这样的限制是因为block 标签的工作方式是双向的。 也就是说,block 标签不仅挖了一个要填的坑,也定义了在父模板中这个坑所填充的内容。如果模板中出现了两个相同名称的 {% block %} 标签,父模板将无从得知要使用哪个块的内容。

{% extends %} 对所传入模板名称使用的加载方法和 get_template() 相同。 也就是说,会将模板名称被添加到 TEMPLATE_DIRS 设置之后。

多数情况下, {% extends %} 的参数应该是字符串,但是如果直到运行时方能确定父模板名,这个参数也可以是个变量。 这使得你能够实现一些很酷的动态功能。



在视图中使用模板
模版是以Html形式显示的。要在django中使用,首先要告诉模版存放在那里。也就是模版加载。打开你的settings.py配置文件,配置如下:
你可以任意指定想要的目录,只要运行 Web 服务器的用户可以读取该目录的子目录和模板文件

使用方式:
1.render
2.render_to_response
3.get_template()
个人比较支持第1和2的方式

locals() 技巧
以下等价于上图,将now等于current_date,既模版里面的变量名。


1
2
3
4
5
1def current_datetime(request):
2    current_date = datetime.datetime.now()
3    return render_to_response(&#x27;current_datetime.html&#x27;, locals())
4
5

给TA打赏
共{{data.count}}人
人已打赏
安全技术

c++ list, vector, map, set 区别与用法比较

2022-1-11 12:36:11

安全技术

利用apache Thrift 进行 node.js和 C++进程间通讯

2021-12-21 16:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索