上一篇:Django教程01-创建一个django项目
下一篇:Django教程03-设计Models(使用数据库)
上一章中,我们在响应函数中返回了一个字符串。这章,我们讲如何使用模板。
1.定义模板文件夹
首先在项目的根目录建立项目的文件夹
#in dir "www"
mkdir templates
其次要在mysite(项目目录)的settings.py中注册
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'),],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
注意:这里的DIRS要以绝对目录的形式给出。
注意 如果设置里有 'APP_DIRS': True, 的话,如果应用在INSTALLED_APPS中注册过,那么应用文件夹下的templates文件夹会被默认搜索。
2.使用模板
首先将需要使用的模板文件放入模板文件夹templates
index.html的内容为
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>使用模板</title>
</head>
<body>
这里使用了模板
</body>
</html>
在响应函数中使用模板(views.py中)
from django.shortcuts import render
from django.shortcuts import HttpResponse
# Create your views here.
def index(request):
#return HttpResponse('Hello world!')
return render(request,'index.html')
访问结果如下图
3.使用模板变量
模板中的变量在view中给出,在模板中使用
模板中使用变量是用{{ }}将变量名环绕,例如{{name}}
我们修改上一步中的模板index.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>使用模板</title>
</head>
<body>
{{content}}
</body>
</html>
home应用的views.py中,给出变量的值
from django.shortcuts import render_to_response
def index(request):
content = '这里使用了模板的变量'
return render_to_response('index.html', {'content':content})
运行结果如下:
views.py中也可以用下面的方式:
from django.shortcuts import render
def index(request):
content = '这里使用了模板的变量'
return render(request, 'index.html', {'content':content})
4.使用模板标签
参考:Django-Templates-built-in-tag-reference
(1)基本用法
模板标签使用{% %}环绕,例如 {% comment "Optional note" %}
这里我们给出一个示例
模板index.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>使用模板</title>
</head>
<body>
<ul>
{% for x in data %}
<li>
<h1>{{x.title}}</h1>
<p>{{x.content}}</p>
</li>
{% endfor %}
</ul>
</body>
</html>
在views.py中给出data的值
from django.shortcuts import render_to_response
def index(request):
data = [{'title':'春节放假通知','content':'春节放假通知内容'},{'title':'习近平访问美国','content':'习近平访问美国详情'},{'title':'96台海危机','content':'96台海危机详情'}]
return render_to_response('index.html', {'data':data})
运行结果如下:
(2)list与dict的解析
django使用jinjia2模板,不能实现list[N] 或 dict['key']的解析。
对于传递来的list,要用{% for item in list %}来解析。
对于传递来的dict,可以用{% for key, value in dict.items %}来解析,或者直接使用{{dict.key}}来获取值
(3)常见的集中标签
(A) for
循环组中的每一个项目,并让这些项目在上下文可用。 举个例子,展示athlete_list中的每个成员。
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>
可以利用{% for obj in list reversed %}反向完成循环。
如果你需要循环一个包含列表的列表,可以通过拆分每一个二级列表为一个独立变量来达到目的。 举个例子,如果你的内容包括一个叫做points的(x,y) 列表,你可以像以下例子一样输出points列表:
{% for x, y in points %}
There is a point at {{ x }},{{ y }}
{% endfor %}
如果你想访问一个字典中的项目,这个方法同样有用。举个例子:如果你的内容包含一个叫做data的字典,下面的方式可以输出这个字典的键和值:
{% for key, value in data.items %}
{{ key }}: {{ value }}
{% endfor %}
for 标签带有一个可选的{% empty %} 从句,以便在给出的组是空的或者没有被找到时,可以有所操作。
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>Sorry, no athletes in this list.</li>
{% endfor %}
</ul>
(B)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 }}过滤器展示出运动员的数量。
正如你所见,if标签之后可以带有一个或者多个{% elif %} 从句,也可以带有一个{% else %}从句以便在之前的所有条件不成立的情况下完成执行。这些从句都是可选的
(C)cycle
每当这个标签被访问,则传出一个它的可迭代参数的元素。第一次访问返回第一个元素,第二次访问返回第二个参数,以此类推.一旦所有的变量都被访问过了,就会回到最开始的地方,重复下去
这个标签在循环中特别有用:
{% for o in some_list %}
<tr class="{% cycle 'row1' 'row2' %}">
...
</tr>
{% endfor %}
第一次迭代产生的HTML引用了 row1类,第二次则是row2类,第三次 又是row1 类,如此类推。
你也可以使用变量,例如,如果你有两个模版变量, rowvalue1和rowvalue2, 你可以让他们的值像这样替换:
{% for o in some_list %}
<tr class="{% cycle 'row1' rowvalue2 'row3' %}">
...
</tr>
{% endfor %}
在某些情况下,您可能需要连续引用一个当前循环的值,而不前进到下一个循环值。要达到这个目的,只需使用“as”来给{% cycle %}一个别名。从那时起(设置别名后),你可以通过将别名作为一个模板变量进行引用,从而随意在模板中插入当前循环的值。如果要将循环值移动到独立于原始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>
5.模板继承
参考:Django-模板继承
(1)模板用法
模板继承涉及到模板标签 block extends
Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可以让您创建一个基本的“骨架”模版,它包含您站点中的全部元素,并且可以定义能够被子模版覆盖的 blocks 。
通过从下面这个例子开始,可以容易的理解模版继承:通过从下面这个例子开始,可以容易的理解模版继承:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css" />
<title>{% block title %}My amazing site{% endblock %}</title>
</head>
<body>
<div id="sidebar">
{% block sidebar %}
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
</ul>
{% endblock %}
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
</body>
</html>
这个模版,我们把它叫作 base.html,并保存在templates文件夹中。它定义了一个可以用于两列排版页面的简单HTML骨架。“子模版”的工作是用它们的内容填充空的blocks。
在这个例子中, block 标签定义了三个可以被子模版内容填充的block。 block 告诉模版引擎: 子模版可能会覆盖掉模版中的这些位置。
子模版可能看起来是这样的:
{% extends "base.html" %}/span>
{% block title %}My amazing blog{% endblock %}
{% block content %}
{% for entry in blog_entries %}
<h2>{{ entry.title }}</h2>
<p>{{ entry.body }}</p>
{% endfor %}
{% endblock %}
extends 标签是这里的关键。它告诉模版引擎,这个模版“继承”了另一个模版。当模版系统处理这个模版时,首先,它将定位父模版——在此例中,就是“base.html”。
那时,模版引擎将注意到 base.html 中的三个 block 标签,并用子模版中的内容来替换这些block。根据 blog_entries 的值,输出可能看起来是这样的:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css" />
<title>My amazing blog</title>
</head>
<body>
<div id="sidebar">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
</ul>
</div>
<div id="content">
<h2>Entry one</h2>
<p>This is my first entry.</p>
<h2>Entry two</h2>
<p>This is my second entry.</p>
</div>
</body>
</html>
请注意,子模版并没有定义 sidebar block,所以系统使用了父模版中的值。父模版的 {% block %} 标签中的内容总是被用作备选内容(fallback)。
(2)多级继承
您可以根据需要使用多级继承。使用继承的一个常用方式是类似下面的三级结构:
- 创建一个 base.html 模版来控制您整个站点的主要视觉和体验。为您的站点的每一个“分支”创建一个base_SECTIONNAME.html 模版。例如, base_news.html, base_sports.html。这些模版都继承自 base.html ,并且包含了每部分特有的样式和设计。
- 为每一种页面类型创建独立的模版,例如新闻内容或者博客文章。这些模版继承对应分支的模版。
- 这种方式使代码得到最大程度的复用,并且使得添加内容到共享的内容区域更加简单,例如分支范围内的导航。
(2)模板使用注意事项
这里是使用继承的一些提示:
如果你在模版中使用 {% extends %} 标签,它必须是模版中的第一个标签。其他的任何情况下,模版继承都将无法工作。
在base模版中设置越多的 {% block %} 标签越好。请记住,子模版不必定义全部父模版中的blocks,所以,你可以在大多数blocks中填充合理的默认内容,然后,只定义你需要的那一个。多一点钩子总比少一点好。
如果你发现你自己在大量的模版中复制内容,那可能意味着你应该把内容移动到父模版中的一个 {% block %} 中。
如果需要获取父模板中的block 的内容,可以使用{{ block.super }} 变量。如果你想要在父block 中新增内容而不是完全覆盖它,它将非常有用。使用{{ block.super }} 插入的数据不会被自动转义(参见下一节),因为父模板中的内容已经被转义。
为了更好的可读性,你也可以给你的 {% endblock %} 标签一个 名字 。例如:
{% block content %}
...
{% endblock content %}
在大型模版中,这个方法帮你清楚的看到哪一个 {% block %} 标签被关闭了。
- 最后,请注意不能在一个模版中定义多个相同名字的block 标签。这个限制的存在是因为block标签的作用是“双向”的。这个意思是,block 标签不仅提供了一个坑去填,它定义向父模版的坑中所填的内容。如果在一个模版中有两个名字一样的 block 标签,模版的父模版将不知道使用哪个block的内容。