Django教程02-使用模板templates

上一篇: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


image.png

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')

访问结果如下图

image.png

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})

运行结果如下:

image.png

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})

运行结果如下:

image.png

(2)list与dict的解析

django使用jinjia2模板,不能实现list[N] 或 dict['key']的解析。

对于传递来的list,要用{% for item in list %}来解析。

对于传递来的dict,可以用{% for key, value in dict.items %}来解析,或者直接使用{{dict.key}}来获取值

(3)常见的集中标签

参考:Django-内置标签与过滤器

(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的内容。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354