The Django Book学习笔记 04 模板
如果使用这种方法制作文章肯定不是一个好方法,尽管它便于你理解是怎么工作的。
def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
所以我们需要将页面设计和Python代码分开来,Django提供了模板系统( Template System ) 来实现这种功能。
模板是一个文本,用于分离文档的表现形式和内容。 模板定义了占位符以及各种用于规范文档该如何显示的各部分基本逻辑(模板标签)。 模板通常用于产生HTML,但是Django的模板也能产生任何基于文本格式的文档。
{{ variable }} 称为变量,意味着在这里插入变量的值。
{% if ordered_warranty %} 被 { 和 % 包围的是模板标签( Template Tag )
模板使用
在mysite目录下运行 # python manage.py shell 进入交互界面
>>> from django import template >>> t = template.Template('I am going to {{ where }}') >>> c = template.Context({'where':'China'}) >>> print(t.render(c)) I am going to China >>> c = template.Context({'where':'America'}) >>> print(t.render(c)) I am going to America
# bad template for name in ('Lusi','John','Julie'): t = Template('Hello,{{ name }}') print(t.render(Context({'name':name}))) # Good t = Template('Hello, {{ name }}') for name in('John','Lusi','Pat'): print(t.render(Context({'name':name})))
>>> from django.template import Template, Context >>> import datetime >>> d = datetime.date(2015,5,2) >>> d.year 2015 >>> d.month 5 >>> d.day 2 >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}') >>> c = Context({'date':d}) >>> t.render(c) u'The month is 5 and the year is 2015'
这个例子使用了一个自定义的类,演示了通过实例变量加一点(dots)来访问它的属性,这个方法适用于任意的对象。
>>> from django.template import Template, Context >>> class Person(object): ... def __init__(self,first_name,last_name): ... self.first_name, self.last_name = first_name, last_name ... >>> t = Template('Hello, {{ person.first_name}} {{person.last_name}}') >>> c = Context({'person':Person('John','Smith')}) >>> t.render(c) u'Hello, John Smith'
点语法也可以用来引用对象的* 方法*。 例如,每个 Python 字符串都有 upper() 和 isdigit() 方法,你在模板中可以使用同样的句点语法来调用它们:
>>> from django.template import Template, Context >>> t = Template('{{ var }}, {{var.upper}}, {{var.isdigit}}') >>> t.render(Context({'var':'hello'})) u'hello, HELLO, False' >>> t.render(Context({'var':'123'})) u'123, 123, True'
注意这里调用方法时并* 没有* 使用圆括号 而且也无法给该方法传递参数;你只能调用不需参数的方法。
>>> from django.template import Template, Context >>> t = Template('Item2 is: {{item.2}}') >>> c = Context({"item":['abc','zhg','666']}) >>> t.render(c) u'Item2 is: 666'
句点查找规则可概括为: 当模板系统在变量名中遇到点时,按照以下顺序尝试进行查找:
-
字典类型查找 (比如 foo["bar"] )
-
属性查找 ( 比如 foo.bar )
-
方法调用 ( 比如 foo.bar() )
-
列表类型索引查找 (比如 foo[bar] )
句点查找可以多级深度嵌套。 例如在下面这个例子中 {{person.name.upper}} 会转换成字典类型查找(person['name'] ) 然后是方法调用( upper() ) :
>>> from django.template import Template, Context >>> a_person = {'name':'John','age':'22'}>>> t = Template('My name is {{ person.name.upper }},{{ person.age}} years old') >>> c = Context({'person':a_person}) >>> t.render(c) u'My name is JOHN,22 years old'
模板加载:
为了减少模板加载调用过程及模板本身的冗余代码,Django 提供了一种使用方便且功能强大的 API ,用于从磁盘中加载模板,
要使用此模板加载API,首先你必须将模板的保存位置告诉框架。在Django创建的目录下的settings.py设置,找到 TEMPLATE_DIRS
注意单义目录后面必须包含一个逗号
TEMPLATE_DIRS = ( '/home/zhg/mysite/templates', )
最省事的方式是使用绝对路径(即从文件系统根目录开始的目录路径)。 如果想要更灵活一点并减少一些负面干扰,可利用 Django 配置文件就是 Python 代码这一点来动态构建 TEMPLATE_DIRS 的内容,如: 例如:
import os.path TEMPLATE_DIRS = ( os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'), )
这个例子使用了神奇的 Python 内部变量 __file__ ,该变量被自动设置为代码所在的 Python 模块文件名。 `` os.path.dirname(__file__)`` 将会获取自身所在的文件,即settings.py 所在的目录,然后由os.path.join 这个方法将这目录与 templates 进行连接。如果在windows下,它会智能地选择正确的后向斜杠”“进行连接,而不是前向斜杠”/”。
完成 TEMPLATE_DIRS 设置后,下一步就是修改视图代码,让它使用 Django 模板加载功能而不是对模板路径硬编码。 返回 current_datetime 视图,进行如下修改:
from django.template.loader import get_template from django.template import Context from django.http import HttpResponse, Http404 import datetime def current_datetime(request): now = datetime.datetime.now() t = get_template('time_now.html') html = t.render(Context({'current_date':now})) return HttpResponse(html)
创建模板代码文件time_now.html 在/home/zhg/mysite/templates/time_now.html
<html><body> It is now {{ current_date }} </body></html>
刷新页面,templates目录的改变不会影响到view.py 只需要更改settings.py 的 TEMPLATE_DIRS
render_to_response()
我们已经告诉你如何载入一个模板文件,然后用 Context渲染它,最后返回这个处理好的HttpResponse对象给用户。 我们已经优化了方案,使用 get_template() 方法代替繁杂的用代码来处理模板及其路径的工作。 但这仍然需要一定量的时间来敲出这些简化的代码。 这是一个普遍存在的重复苦力劳动。Django为此提供了一个捷径,让你一次性地载入某个模板文件,渲染它,然后将此作为 HttpResponse返回。
该捷径就是位于 django.shortcuts 模块中名为 render_to_response() 的函数
from django.shortcuts import render_to_response import datetime def current_datetime(request): now = datetime.datetime.now() return render_to_response('current_datetime.html', {'current_date': now})
我们不再需要导入 get_template 、 Template 、 Context 和 HttpResponse 。相反,我们导入django.shortcuts.render_to_response 。 import datetime 继续保留.
在 current_datetime 函数中,我们仍然进行 now 计算,但模板加载、上下文创建、模板解析和HttpResponse 创建工作均在对 render_to_response() 的调用中完成了。 由于 render_to_response() 返回 HttpResponse 对象,因此我们仅需在视图中 return 该值。