Django 模板语法
基本的模板标签
标签
if/else
{% if %}
标签检查(evaluate)一个变量,如果这个变量为真(即,变量存在,非空,不是布尔值假),系统会显示在
{% 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 %}
{% if %}
标签接受 and,or 或者 not 关键字来对多个变量做判断,或者对变量取反(not),不允许在同一个标签中同时使用 and 和 or ,因为逻辑上可能模糊的。
系统不支持用圆括号来组合比较操作。 如果你确实需要用到圆括号来组合表达你的逻辑式,考虑将它移到模板之外处理,然后以模板变量的形式传入结果吧。
并没有
{% elif %}
标签, 请使用嵌套的
{% if %}
标签来达成同样的效果。
一定要用 {% endif %} 关闭每一个 {% if %} 标签。
例如:
{% if athlete_list and coach_list %}
Both athletes and coaches are available.
{% 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 %}
以上都OK,但是,下面的不行。
{% if athlete_list and coach_list or cheerleader_list %}
include 模板标签
{% include %}
标签允许在(模板中)包含其它的模板的内容。 标签的参数是所要包含的模板名称,可以是一个变量,也可以是用单/双引号硬编码的字符串。 每当在多个模板中出现相同的代码时,就应该考虑是否要使用
{% include %}
来减少重复。
{% include 'nav.html' %}
{% include nav.html %}
{% include 'includes/nav.html' %}
{% include template_name %}
和在
get_template()
中一样, 对模板的文件名进行判断时会在所调取的模板名称之前加上来自
TEMPLATE_DIRS
的模板目录。
所包含的模板执行时的 context 和包含它们的模板是一样的。
如果{% include %}标签指定的模板没找到,Django将会在下面两个处理方法中选择一个:
- 如果 DEBUG 设置为 True ,你将会在 Django 错误信息页面看到 TemplateDoesNotExist 异常。
- 如果 DEBUG 设置为 False ,该标签不会引发错误信息,在标签位置不显示任何东西。
模板继承
在实际应用中,你将用 Django 模板系统来创建整个 HTML 页面。 这就带来一个常见的 Web 开发问题: 在整个网站中,如何减少共用页面区域(比如站点导航)所引起的重复和冗余代码?
解决该问题的传统做法是使用 服务器端的
includes
,你可以在 HTML 页面中使用该指令将一个网页嵌入到另一个中。 事实上, Django 通过刚才讲述的
{% include %}
支持了这种方法。 但是用 Django 解决此类问题的首选方法是使用更加优雅的策略---- 模板继承 。
本质上来说,模板继承就是先构造一个基础框架模板,而后在其子模板中对它所包含站点公用部分和定义块进行重载。
Django 的模板继承系统可以视为服务器端
include
的逆向思维版本。 你可以对那些 不同 的代码段进行定义,而不是 共同 代码段。
步骤:
第一步是定义
基础模板
, 该框架之后将由
子模板
所继承。 以下是我们目前所讲述范例的基础模板:
示例代码:
base.html
<!DOCTYPE HTML PUBLIC -//W3C//DTD HTML 4.01//EN>
<html lang=en>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<h1>My helpful timestamp site</h1>
{% block content %}{% endblock %}
{% block footer %}
<hr>
<p>Thanks for visiting my site.</p>
{% endblock %}
</body>
</html>
这个叫做 base.html 的模板定义了一个简单的 HTML 框架文档,我们将在本站点的所有页面中使用。 子模板的作用就是重载、添加或保留那些块的内容。
我们使用一个以前已经见过的模板标签:
{% block %}
。 所有的
{% block %}
标签告诉模板引擎,子模板可以重载这些部分。 每个
{% block %}
标签所要做的是告诉模板引擎,该模板下的这一块内容将有可能被子模板覆盖。
现在我们已经有了一个基本模板,我们可以修改
current_datetime.html
模板来 使用它:
current_datetime.html:
{% extends base.html %}
{% block title %}The current time{% endblock %}
{% block content %}
<p>It is now {{ current_date }}.</p>
{% endblock %}
hours_ahead
{% extends base.html %}
{% block title %}Future time{% endblock %}
{% block content %}
<p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>
{% endblock %}
模板继承工作方式
在加载 current_datetime.html 模板时,模板引擎发现了
{% 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 %}
的参数应该是字符串,但是如果直到运行时方能确定父模板名,这个参数也可以是个变量。 这使得你能够实现一些很酷的动态功能。
自定义过滤器
在 app 目录下创建 templatetags 目录,然后编写自定义过滤器类,例如 PaginatorFilter.py
内容如下:
#!/usr/local/bin/python
# encoding: utf-8
__author__ = 'l00289062'
分页使用的过滤器
@version: ''
@author: U{Tyrael Lau<mailto:[email protected]>}
@see: http://liuzhijun.iteye.com/blog/1884630
from django import template
register = template.Library()
@register.filter(name=status)
def status_filter(value, pages=None):
if pages.is_curr_page(value):
return active
if pages.is_page_valid(value):
return None
else:
return disabled
然后在模板中引入自定义过滤器
{% load PaginatorFilter %}
既可使用过滤器
status
。
假设过滤器为 pages | status:1,那么对应到代码上来就是:
def status_filter(value, pages=None):
- value = pages
- pages = 1