在前一章中,HTML是直接被硬编码在 Python views.py代码中,如下:
from django.http import HttpResponse import datetime def hello(request): return HttpResponse("Hello world") def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
在实际的项目开发中,站点页面设计的修改往往比底层 Python 代码的修改要频繁得多,如果每次对页面设计所进行的任何改变都必须对底层Python 代码进行相应的修改,是很难满足实际的项目开发需要的。因此, Django开发了一套模板系统 (Template System)来实现将页面的设计和Python的代码分离开的开发模式,本章节我们只通过简单的实例来说明模板系统如何运用,具体的模板系统的语法和原理,请参考《The Django Book》网站。
Django模板是一个文本,用于分离文档的表现形式和内容。 模板定义了占位符以及各种用于规范文档该如何显示的各部分基本逻辑(模板标签)。 模板通常用于产生HTML,但是Django的模板也可以产生任何基于文本格式的文档。
在Python代码中使用Django模板的最基本方式如下:
>>> from django import template >>> t = template.Template('My name is {{ name }}.') >>> c = template.Context({'name': 'Haozi'}) >>> print t.render(c) My name is Haozi. >>> c = template.Context({'name': 'Wuch'}) >>> print t.render(c) My name is Wuch.
创建一个 Template 对象的方法就是直接实例化它。 Template 类就在 django.template 模块中,构造函数接受一个“原始模板代码”作为参数。
一旦创建一个 Template 对象,就可以用 context 来传递数据给它。 一个context是一系列变量和它们值的集合。
>>> from django.template import Context, Template >>> t = Template('My name is {{ name }}.') >>> c = Context({'name': 'Stephane'}) >>> t.render(c) u'My name is Stephane.'
需要注意的是,t.render(c)返回值是一个Unicode对象,不是普通的字符串。 你可以通过字符串前的u来区分。 在Django框架中,会一直使用Unicode字符串对象而不是普通的字符串。
Python的字典数据类型就是关键字和它们值的一个映射,Context 和字典很类似。context变量名必须由英文字符开始 (A-Z或a-z)并可以包含数字字符、下划线和小数点。
Context在Django里是 Context 类,她的构造函数带有一个可选的参数: 一个字典映射变量和它们的值。 调用 Template 对象 的 render() 方法时,传递context来填充模板参数的值。
一旦有了 模板 对象,我们可以通过它渲染多个context来获得不同的动态页面效果, 例如:
>>> from django.template import Template, Context >>> t = Template('Hello, {{ name }}') >>> print t.render(Context({'name': 'John'})) Hello, John >>> print t.render(Context({'name': 'Julie'})) Hello, Julie >>> print t.render(Context({'name': 'Pat'})) Hello, Pat
现在我们使用模板技术来创建视图。 重新打开我们在前一章在 mysite.views 中创建的 current_datetime 视图:
from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
依据用 Django 模板系统把该视图修改为如下代码:
from django.template import Template, Context from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() t = Template("<html><body>It is now {{ current_date }}.</body></html>") html = t.render(Context({'current_date': now})) return HttpResponse(html)
现在我们虽然使用了模板系统,但并未真正的实现数据与表现的分离,模板仍然嵌入在Python代码里。 下面我们在改进一下代码,将模板置于一个单独的文件中,并在视图中加载模板文件来最终解决表现与数据分开的问题。
Django 为我们提供了一种使用方便且功能强大的 API ,用于从磁盘中加载模板。要使用此模板加载API,首先我们需将模板的存放位置告诉框架,在settings.py中配置模板文件的保存路径。打开mysite settings.py配置文件,找到TEMPLATE_DIRS设置项,加上文档模板的保存路径。
告诉 Django 加载模板时,在哪里查找模板。 选择一个目录用于存放模板并将其添加到 TEMPLATE_DIRS 中,本例子中我们在mysite目录下创建子目录templates来放置模板文件,配置TEMPLATE_DIRS可以使用绝对路径来进行配置(即从文件系统根目录开始的目录路径)。
TEMPLATE_DIRS = ( # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". # Always use forward slashes, even on Windows. # Don't forget to use absolute paths, not relative paths. 'C:\My Files\Python Projects\mysite\templates', )
下面我们是使用Python 代码这一点来构建动态的TEMPLATE_DIRS路劲的内容,代码如下:
import os.path TEMPLATE_DIRS = ( # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". # Always use forward slashes, even on Windows. # Don't forget to use absolute paths, not relative paths. os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'), )
这段代码使用了Python 内部变量 __file__ ,该变量被自动设置为settings.py 文件所在的目录,然后由os.path.join 这个方法将这目录与 templates 进行连接。在windows下,它会智能地选择正确的后向斜杠”“进行连接,而不是前向斜杠”/”。
接下来修改视图代码,框架使用 Django 模板加载功能来返回 current_datetime 视图:
from django.template.loader import get_template from django.template import Context from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() t = get_template('current_datetime.html') html = t.render(Context({'current_date': now})) return HttpResponse(html)
同时,在模板目录中创建包括以下模板代码 current_datetime.html 文件:
<html><body>It is now {{ current_date }}.</body></html>
这样如下图,是模板直接在IE中浏览的效果。
注意:模板的目录结构,否则无法正常加载模板,mytime URL最后的访问效果如下图:
我们已经告诉你如何载入一个模板文件,然后用 Context渲染它,最后返回这个处理好的HttpResponse对象给用户。同时,Django提供了一个更方便简单的函数,让我们一次性地载入某个模板文件并渲染它,最后直接作为HttpResponse返回。
该快捷方式就是位于 django.shortcuts 模块中名为 render_to_response() 的函数。下面代码就是使用 render_to_response() 重新编写过的 current_datetime 范例。
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})
render_to_response() 的第一个参数必须是要使用的模板名称。第二个参数是为该模板创建 Context 时所使用的字典。
本章我们简要阐述了Django动态网页,以及如何通过加载模板文件来实现动态网页。关于Django模板的语法规则,还支持包含、继承等复杂的关系,进一步详细的模板语法请大家参考Django开发手册。
下一章我们将介绍Django是如何访问数据库的内容——模型。