Bottle Template
1 Bottle SimpleTemplate 的简单使用场景
-
简单的花括号
>>> tpl = SimpleTemplate('Hello { {name}}!') >>> tpl.render(name='World') u'Hello World!'
-
带有 Python 语法关键字的语句
>>> template('Hello { {name.title() if name else "stranger"}}!', name=None) u'Hello stranger!' >>> template('Hello { {name.title() if name else "stranger"}}!', name='mArC') u'Hello Marc!'
源码分析
BaseTemplate
基类
- 构造函数中传递进来的有两个参数
- template: 直接传递字符串,保存到
- filename: 传递模板文件的名字,将从该文件中读取所有内容
- 构造函数中,读取完 template 之后,就进行
self.parse
, 将在子类中进行
class BaseTemplate(object):
def __init__(self, template='', filename='<template>'):
self.source = filename
if self.source != '<template>':
fp = open(filename)
template = fp.read()
fp.close()
self.parse(template)
def parse(self, template): raise NotImplementedError
def render(self, **args): raise NotImplementedError
@classmethod
def find(cls, name):
files = [path % name for path in TEMPLATE_PATH if os.path.isfile(path % name)]
if files:
return cls(filename = files[0])
else:
raise TemplateError('Template not found: %s' % repr(name))
SimpleTemplate
类
class SimpleTemplate(BaseTemplate):
re_python = re.compile(r'^\s*%\s*(?:(if|elif|else|try|except|finally|for|while|with|def|class)|(include.*)|(end.*)|(.*))')
re_inline = re.compile(r'\{\{(.*?)\}\}')
dedent_keywords = ('elif', 'else', 'except', 'finally')
def parse(self, template):
indent = 0
strbuffer = []
code = []
self.subtemplates = {}
class PyStmt(str):
def __repr__(self): return 'str(' + self + ')'
def flush():
# 将缓存的 strbuffer 字符拼接起来,添加到 code 中
# 这样有多行普通字符串,在执行编译代码中时,也只需要执行一条语句,节省时间
if len(strbuffer):
code.append(" " * indent + "stdout.append(%s)" % repr(''.join(strbuffer)))
code.append("\n" * len(strbuffer)) # to preserve line numbers
del strbuffer[:]
for line in template.splitlines(True):
m = self.re_python.match(line)
# 包含 % 加 python 关键字的字符串
if m:
# 先跳过&