在使用web.py进行开发的时候避免不了会在template中使用$code来定义一些小函数,按照web.py的文档来看,$code之内能包含任意的python代码,但在实际使用的时候却经常发现不是这个样子的,只有特定的函数可以在$code中出现,比如说默认情况下在template中可以使用 len 函数,但却不能使用 str,为什么?
仔细分析web.py的源码可以发下:
所有有关template处理的都包含在template.py文件中。
调用template最终会调用到BaseTemplate 的_compile方法,其中_compile的实现细节为
def _compile(self, code):
env = self.make_env(self._globals or {}, self._builtins)
exec(code, env)
return env['__template__']
make_env又做了什么事呢?
def make_env(self, globals, builtins):
return dict(globals,
__builtins__=builtins,
ForLoop=ForLoop,
TemplateResult=TemplateResult,
escape_=self._escape,
join_=self._join
)
注意,这里的关键点儿就在于__builtins__了,默认情况下Template的builtins为TEMPLATE_BUILTINS,下面注意TEMPLATE_BUILTINS的声明。
TEMPLATE_BUILTIN_NAMES = [
"dict", "enumerate", "float", "int", "bool", "list", "long", "reversed",
"set", "slice", "tuple", "xrange",
"abs", "all", "any", "callable", "chr", "cmp", "divmod", "filter", "hex",
"id", "isinstance", "iter", "len", "max", "min", "oct", "ord", "pow", "range",
"True", "False",
"None",
"__import__", # some c-libraries like datetime requires __import__ to present in the namespace
]
import __builtin__
TEMPLATE_BUILTINS = dict([(name, getattr(__builtin__, name)) for name in TEMPLATE_BUILTIN_NAMES if name in __builtin__.__dict__])
由此可以看出template默认情况下是不包含str操作的。
如果要在程序中使用str操作符,又该如何操作呢?其实很简单,在初始化template时添加即可,具体代码如下:
# set global base template
render = web.template.render("app/views/", cache = config.cache, globals={'str': str})