在使用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})