接下来,我们开始学习如何使用模板系统,但我们并不和前面说的View相结合,我们的这里的目的是展示模板系统是如何独立于Django框架运行的。下面是在pyhon代码中使用Django模板系统的基础例子:
1.通过提供原生文本代码创建Template模板对象
2.调用Template对象的render()方法并传入所给的参数(上下文文本)。
>>> from django import template >>> t = template.Template('My name is {{ name }}.') >>> c = template.Context({'name': 'Adrian'}) >>> print t.render(c) My name is Adrian. >>> c = template.Context({'name': 'Fred'}) >>> print t.render(c) My name is Fred.
创建模板对象
最简单的创建Template对象的方法就是直接实例化一个出来。Template类在Django.Template module里,构造函数需要一个参数,原生template 代码。接下来我们将一步步看看在python交互解释器中是如何工作的。
在myiste项目中,输入 python manage.py shell 启动交互解释器。
(原文中此处解释了为什么没有使用python而是使用了python shell,主要是此处使用python shell 方便了配置。)
一个简单的例子:
>>> from django.template import Template >>> t = Template('My name is {{ name }}.') >>> print t
你会在显示中看到:
<django.template.Template object at 0xb7d5f24c>
0xb7d5f24c 每次都是不一样的,但他们是有关系的,是python用来识别Template对象的标识。
调用模板
一旦你创建模板完毕,你可以通过把数据传给一个context然后传给模板,context是一个简单的模板变量的合集,它包含了模板中变量的值。
context是django.template module中的值。它的构造函数包括一个参数,字典映射变量给值。调用Template对象的render()方法来填充模板。、:
>>> from django.template import Context, Template >>> t = Template('My name is {{ name }}.') >>> c = Context({'name': 'Stephane'}) >>> t.render(c) u'My name is Stephane.'
多上下文,多模板
一旦你创建了Template对象,你可以给它赋予多个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
不论什么时候你这样使用模板,创建模板对象一次,然后显示它们多次比较有效率:
# 坏的编码 for name in ('John', 'Julie', 'Pat'): t = Template('Hello, {{ name }}') print t.render(Context({'name': name}))
# 好的编码 t = Template('Hello, {{ name }}') for name in ('John', 'Julie', 'Pat'): print t.render(Context({'name': name}))
上下文变量查找
之前的例子中,我们都是把简单的变量传递给了上下文Context,实际上,模板系统还可以处理更为复杂的数据类型。
>>> from django.template import Template, Context >>> person = {'name': 'Sally', 'age': '43'} >>> t = Template('{{ person.name }} is {{ person.age }} years old.') >>> c = Context({'person': person}) >>> t.render(c) u'Sally is 43 years old.'
同样,我们可以使用自定义类:
>>> 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中的string类型的对象有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'
注意,在调用方法的时候不需要外面的括号,也不可以向方法传递参数,你只可以调用无参方法。
最后,点还可以用来访问list中的序列,如下:
>>> from django.template import Template, Context >>> t = Template('Item 2 is {{ items.2 }}.') >>> c = Context({'items': ['apples', 'bananas', 'carrots']}) >>> t.render(c) u'Item 2 is carrots.'
负数序号是不允许的,{{items.-1}}会引发TemplateSyntaxError异常。
方法调用行为
方法调用要比其他类型的查找稍微复杂一些,下面是一些需要记住的:
如果在查找方法期间,方法执行过程中出现了异常,异常将会被弹出来,除非异常拥有silent_variable_failure标记而且该标记为true.如果异常拥有silent_variable_failure标记,变量将会被赋予空字符,如下例:
>>> t = Template("My name is {{ person.first_name }}.") >>> class PersonClass3: ... def first_name(self): ... raise AssertionError, "foo" >>> p = PersonClass3() >>> t.render(Context({"person": p})) Traceback (most recent call last): ... AssertionError: foo
>>> class SilentAssertionError(AssertionError): ... silent_variable_failure = True >>> class PersonClass4: ... def first_name(self): ... raise SilentAssertionError >>> p = PersonClass4() >>> t.render(Context({"person": p})) u'My name is .'
1.方法调用只在方法不需要参数的时候起作用,否则,系统将会移动到下一个查找类型。
2.显示,有些方法会有一些副作用,安全漏洞,允许模板系统访问他们。
譬如,有一个BankAccount类型的对象,该对象有个delete()方法。如果模板系统包括类似的语句{{account.delete}},account是一个BankAccount类型的对象,该对象会被展示模板时被删除。
为了防止对象被删除,给方法添加一个alters_data的标记:
def delete(self): # Delete the account delete.alters_data = True
模板系统不会执行任何被这样标记了的方法,在这个例子中,展示模板时,delete()方法不会被执行,取而代之的是静默的失败。
无效的变量如何被处理
默认情况下,如果变量在模板系统中不存在,将返回空字符串,静默地失败。考虑下面的例子:
>>> from django.template import Template, Context >>> t = Template('Your name is {{ name }}.') >>> t.render(Context()) u'Your name is .' >>> t.render(Context({'var': 'hello'})) u'Your name is .' >>> t.render(Context({'NAME': 'hello'})) u'Your name is .' >>> t.render(Context({'Name': 'hello'})) u'Your name is .'
系统静默地失败而非抛出异常是因为要平滑地处理异常,上面的例子中,所有的查找失败都是因为变量大小写错误或是名字不对,在现实世界中,仅仅因为这样的错误而使网站不可访问时不可接受的。
上下文对象
多数情况下你将会实例化一个Context对象,利用pythong字典的特性,你可以在创建了Context对象之后对其中的的每一项进行添加或是删除。
>>> from django.template import Context >>> c = Context({"foo": "bar"}) >>> c['foo'] 'bar' >>> del c['foo'] >>> c['foo'] Traceback (most recent call last): ... KeyError: 'foo' >>> c['newvariable'] = 'hello' >>> c['newvariable'] 'hello'