Friday, January 3, 2014

mako二三事 -- Context

Context是mako中的一个重要概念,负责模板与外界所有的数据传递。在模板中,我们可以用变量context来访问它。Context由两个重要组成部分组成,一个是类似StringIO的输出缓存buffer,另一个是存储参数(render参数、built-in参数等)的字典,该字典中的所有参数都可以直接在模板中使用。

from mako.template import Template
from mako.runtime import Context
from StringIO import StringIO

mytemplate = Template("hello, ${name}!")
buf = StringIO()
ctx = Context(buf, name="jack")
mytemplate.render_context(ctx)
print buf.getvalue()


1. 输出缓存

模板中所有的文本,${}包含的表达式,context.write()等方式都可直接将结果保存到Context中的输出缓存buffer中。不过尽量不要直接去操纵这个变量,因为在filter/cache等场景下中,该变量有可能会改变。


2. 参数字典

render传入模板的参数都会放入到context的参数字典中,在模板解析时,mako会判断一个变量是否已经被定义(如赋值),如果未定义,就会在模板开头从context中载入这个变量,如:

username = context.get('username', UNDEFINED)

因此,在模板中可以直接按名字引用context中存储的参数变量。


3. UNDEFINED

UNDEFINED是mako中定义的一个类mako.runtime.Undefined的一个实例,主要用于处理模板中可能会出现的未定义变量。不过因为UNDEFINED在转成字符串是是raise NameError("Undefined”),所以开发者看不出究竟是哪个变量没有定义。这给开发带来了一定的麻烦。因此,mako引入了strict_undefined参数,只要在Template、TemplateLookup中传入strict_undefined=True参数,那么mako遇到未定义变量将直接抛出NameError,如定义了strict_undefined=True之后,mako生成的代码是:

try:
    mytest = context['mytest']
except KeyError:
    raise NameError("'mytest' is not defined")

而不是

mytest= context.get('mytest', UNDEFINED)

不过如果希望在模板中自己去判断变量是否存在,那么就需要用类似:

% if someval is UNDEFINED:
    someval is: no value
% else:
    someval is: ${someval}
% endif



${'not defined' if someval is UNDEFINED else someval }

这种方式来判断了,这个时候就需要设置strict_undefined=False。


4. 模板之间的变量共享

前面提到了,在模板中定义的所有变量都是render_body的私有变量,因此如果需要在几个不同的模板之间(一次渲染请求中)共享某个参数,就需要使用context来进行传递了。

但上面也提到了context很有可能在一次渲染过程中,几个不同模板间会有不同,那么如何来做到变量的共享呢?

其实,我们可以在render的时候传入一个空的字典,不是None,是{},如:

output = template.render(attributes={})

接下来,我们就可以在模板中用如下方式来赋值、引用了:

<%
    attributes['foo'] = 'bar'
%>
'foo' attribute is: ${attributes['foo']}


5、context常见使用方法

context是一个类似字典的数据结构,常见的一些用法如下:
* context[key] / context.get(key, default=None) 直接访问context中的参数字典
* keys()   得到context中所有参数名
* kwargs  得到context中所有参数的一份拷贝
* write() 写入到输出缓存
* lookup 得到TemplateLookup实例

No comments:

Post a Comment