Django学习笔记(第四节)模板

来源:互联网 发布:网络写作集剧本编写 编辑:程序博客网 时间:2024/06/04 18:08

在之前的学习中,所有的html内容都是硬编码在python文件中的,这不符合MVC模式,不便于开发和维护,所以需要将页面设计和python代码分离。我们可以使用Django的模板系统来完成这个。

模板总体上说有点类似于JSP,但是不同之处在于Django模板不能够执行python语句,而JSP可以执行Java语句。

在使用模板时,有两个重要的类:Template,Context

看名字就可以知道,第一个是模板类,第二个是上下文。

模板包括模板标签、过滤器、变量等。

本节中将依次学习一下三个内容:模板标签,Django模板设计理念,在视图中使用模板。


标签

if/else 检查一个变量的真假,从而显示标签内的内容,这个用法与一般语言的选择语句是一致的,如组合条件(and,or等)、多个elif。例如:

{% if today_is_weekend %}    <p>Welcome to the weekend!</p>{% endif %}

today_is_weekend变量为真则显示<p>标签对中的内容。

{% else%} 标签是可选的。最后以{% endif %}结束if语句。

在python和Django中,有一些对象相当于布尔值False:

1.空列表[]        2.空元组()           3.空字符串""         4.空字典{}           5.零值0         6.特殊对象None         7.对象False


for    循环语句,与python的for语句用法一致,以{%endfor %}结束。例如:

<ul>{% for athlete in athlete_list %}    <li>{{ athlete.name }}</li>{% endfor %}</ul>
但是需要注意的是Django不支持退出循环操作,也就是说break语句和continue语句都无法使用。

在for循环中有一个叫做“forloop”的模板变量,可以提供一些循环进度信息。

{% for item in todo_list %}    <p>{{ forloop.counter }}: {{ item }}</p>{% endfor %}
forloop.counter 总是一个表示当前循环的执行次数的整数计数器。 这个计数器是从1开始的,所以在第一次循环时forloop.counter 将会被设置为1。

forloop.counter0 类似于forloop.counter ,但是它是从0计数的。 第一次执行循环时这个变量会被设置为0。

forloop.revcounter 是表示循环中剩余项的整型变量。 在循环初次执行时forloop.revcounter 将被设置为序列中项的总数。 最后一次循环执行中,这个变量将被置1。

forloop.revcounter0 类似于forloop.revcounter ,但它以0做为结束索引。在第一次执行循环时,该变量会被置为序列的项的个数减1。

forloop.first 是一个布尔值,如果该迭代是第一次执行,那么它被置为```` 在下面的情形中这个变量是很有用的:

System Message: WARNING/2 (<string>, line 1071);backlink

Inline literal start-string without end-string.
forloop.last 是一个布尔值;在最后一次执行循环时被置为True。 一个常见的用法是在一系列的链接之间放置管道符(|)

forloop.parentloop 是一个指向当前循环的上一级循环的forloop 对象的引用(在嵌套循环的情况下)。

注意:由于forloop是Django的内部变量,所以在Django中应该避免使用forloop作为自己定义的变量。

forloop在for循环结束时将会失效,不可访问。


ifequal/ifnotequal 用于比较两个值,它支持可选的{%else%} 标签,例如:

{% ifequal section 'sitenews' %}    <h1>Site News</h1>{% else %}    <h1>No News Here</h1>{% endifequal %}
注意:只有模板变量,字符串,整数和小数可以作为 {%ifequal %} 标签的参数。其他类型例如Python的字典类型、列表类型、布尔类型,不能用在{% ifequal%} 中。

{# #} 用于添加注释相当于html中的<!-- -->,需要注意到是不能跨行。

如果想要多行注释,需要使用{% comment %}模板标签,并以{% endcomment %}结束。


过滤器

{{ name|lower }}显示的内容是变量 {{name }} 被过滤器 lower 处理后的结果,它功能是转换文本为小写。

过滤管道可以被* 套接* ,既是说,一个过滤器管道的输出又可以作为下一个管道的输入,如此下去。

下面的例子实现查找列表的第一个元素并将其转化为大写。{{ my_list|first|upper }}

有些过滤器有参数。 过滤器的参数跟随冒号之后并且总是以双引号包含。 例如:{{ bio|truncatewords:"30" }}



理念与局限

Django并不严格要求使用它的模板,也可以在Django中非常容易的使用其他模板。但是它是很好用的,一下内容摘自1.4版中文翻译:


业务逻辑应该和表现逻辑相对分开 。我们将模板系统视为控制表现及表现相关逻辑的工具,仅此而已。 模板系统不应提供超出此基本目标的功能。

出于这个原因,在 Django 模板中是不可能直接调用 Python 代码的。 所有的编程工作基本上都被局限于模板标签的能力范围。 当然, 有可能写出自定义的模板标签来完成任意工作,但这些“超范围”的 Django 模板标签有意地不允许执行任何 Python 代码。

语法不应受到 HTML/XML 的束缚 。尽管 Django 模板系统主要用于生成 HTML,它还是被有意地设计为可生成非 HTML 格式,如纯文本。 一些其它的模板语言是基于 XML 的,将所有的模板逻辑置于 XML 标签与属性之中,而 Django 有意地避开了这种限制。 强制要求使用有效 XML 编写模板将会引发大量的人为错误和难以理解的错误信息,而且使用 XML 引擎解析模板也会导致令人无法容忍的模板处理开销。

假定设计师精通 HTML 编码 。模板系统的设计意图并不是为了让模板一定能够很好地显示在 Dreamweaver 这样的所见即所得编辑器中。 这种限制过于苛刻,而且会使得语法不能像目前这样的完美。 Django 要求模板创作人员对直接编辑 HTML 非常熟悉。

假定设计师不是 Python 程序员 。模板系统开发人员认为:模板通常由设计师而非程序员来编写,因此不应被假定拥有Python开发知识。

当然,系统同样也特意地提供了对那些 Python 程序员进行模板制作的小型团队的支持。 它提供了一种工作模式,允许通过编写原生 Python 代码进行系统语法拓展

目标并不是要发明一种编程语言 。目标是恰到好处地提供如分支和循环这一类编程式功能,这是进行与表现相关判断的基础。


在视图中使用模板

模板加载

打开settings.py配置文件,找到TEMPLATE_DIRS这项设置。它的默认设置是一个空元组(tuple),加上一些自动生成的注释。

在这里需要注意1.4版本和1.6以上版本是有区别的(1.5没有实验,不清楚具体与那个版本情况相同)。

1.4版本直接找到TEMPLATE_DIRS设置为:

TEMPLATE_DIRS = (    '/home/django/mysite/templates',)
即可

1.6以上版本是找不到这个元组的,但是查看代码会有这样一句话:BASE_DIR = os.path.dirname(os.path.dirname(__file__))

与我们要找的内容很相似,在这行代码下面,添加之前的TEMPLATE_DIRS代码

注意:这里与URL中的设置一样,在最后一个URL结束时是有一个逗号的,用来区别元组和block expression


下一步:

在之前建立的site项目中创建文件夹templates,创建模板文件current_datetime.html并输入以下代码:

<html><body>It is now {{ current_date }}.</body></html>

修改views.py文件,导入类:

from django.template.loader import get_template
from django.template import Context

修改方法:

def current_datetime(request):    now = datetime.datetime.now()    #get_template()方法以模板名称为参数,这里以current_datetime.html为例    t = get_template('current_datetime.html')    html = t.render(Context({'current_date': now}))    return HttpResponse(html)

完成以上步骤,模板代码就已经编写完成了,启动服务访问http://127.0.0.1:8000/time/查看页面结果。


render_to_response()

在上面的已经完整的使用模板,但是代码并不简洁,Django提供了更简洁,一次性载入某个模板文件的方法,并实现Context类的渲染,然后作为HttpResponse返回。

从新用render_to_response()方法编写模板,代码如下:

from django.shortcuts import render_to_responseimport datetimedef current_datetime(request):    now = datetime.datetime.now()    return render_to_response('current_datetime.html', {'current_date': now})
内容简洁了很多。


关于模板的一些事项:

1. 如果模板在子目录中,那么只需要在get_template()方法中把子目录也填写上即可。如:t = get_template('dateapp/current_datetime.html')。

同理render_to_response()方法也是一样的。

2.{% include "nav.html" %}标签。这个标签允许嵌套其他模板,类似于HTML的include。可以提高代码重用。

如果include的模板没有找到,在debug模式下将报错,在关闭debug的时候,include的地方将不会显示任何内容。

3.同样是解决上面的问题Django还有一套方案就是继承。{%extends "base.xml"%}。base.xml是父模板,在这个模板中设置标签用于子模板自定义。

那么在子模板中,只需要将模板版extends就可以直接得到父模板的所有内容,剩下的只要编写各自独特的内容就可以了。





0 0
原创粉丝点击