前两篇文章主要说明了web.py的模板系统将模板文件处理后得到的结果:__template__()
函数。本文主要讲述模板文件是如何变成__template__()
函数的。
Render和frender
一般来说,更常用的是Render类,该类会处理整个目录下的模板,还支持缓存和嵌套模板。不过这些其实都和模板本身的解析基本没关系,以后再说明这个类的实现和用途。这里我们使用frender()
函数:
1 2 3 4 5 |
def frender(path, **keywords): """Creates a template from the given file path. """ return Template(open(path).read(), filename=path, **keywords) |
这个函数相当简单,只作了一键事情,就是读取模板文件内容,然后交给Template类处理,并且返回一个Template类实例。从这里也可以看出,整个模板的解析,只和Template类有关,frender是来打杂的。
Template类
Template实例的效果
当我们根据一个模板内容创建一个Template类实例t后,我们可以调用该实例,这相当于调用模板对应的__template__()
函数,得到的结果是一个TemplateResult实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
In [7]: t = web.template.frender("templates/hello.html") # coding: utf-8 def __template__ (name): __lineoffset__ = -4 loop = ForLoop() self = TemplateResult(); extend_ = self.extend extend_([u'hello, ', escape_(name, True), u'\n']) return self In [8]: print t("xxxx") hello, xxxx In [9]: print type(t("xxxx")) <class 'web.template.TemplateResult'> |
Template实例化过程
Template实例化过程是把模板转换成HTML内容的实质性步骤,不过这个过程比较复杂。但是,概括的来讲,这个过程和Template的__init__()
函数中的步骤差不都差不多。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# Template类的__init__()函数 def __init__(self, text, filename='', filter=None, globals=None, builtins=None, extensions=None): self.extensions = extensions or [] text = Template.normalize_text(text) code = self.compile_template(text, filename) _, ext = os.path.splitext(filename) filter = filter or self.FILTERS.get(ext, None) self.content_type = self.CONTENT_TYPES.get(ext, None) if globals is None: globals = self.globals if builtins is None: builtins = TEMPLATE_BUILTINS BaseTemplate.__init__(self, code=code, filename=filename, filter=filter, globals=globals, builtins=builtins) |
首先把,参数里除了text以外的参数忽略掉,然后来看下对text的处理过程(text就是模板的内容)。整个过程概括的说有如下步骤:
- 对text作归一化处理:
text = Template.normalize_text(text)
, 主要换行符统一成n,删除BOM字符串,将$替换成$$,这个就是简单的字符串处理。 - 编译模板得到编译后的Python字节码code:
code = self.compile_template(text, filename)
,code就是之前已经提到过的__template__()
函数。 - 调用父类(BaseTemplate)的
__init__()
函数:创建__template__()
函数的执行环境,并且实现可调用功能。
其他没有说明的代码,暂时都可以忽略,不会影响你理解Template的实例化过程。从上面的步骤可以看出,Template实例化的过程主要有两个:生成__template__()
函数的代码并编译,以及创建__template__()
函数的执行环境。
生成__template__()函数的代码
这个是模板生成过程中最长最复杂的一段,会应用到Python的token分析功能以及动态编译功能。还记得第一篇里,我们搭建实验环境的时候,修改了web.py源码,在一个地方插入了一行打印语句么?没错,就是这个compile_template()
函数,我们现在来看看它是如何生成__template__()
函数的代码的。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def compile_template(self, template_string, filename): code = Template.generate_code(template_string, filename, parser=self.create_parser())late_string, filename, parser=self.create_parser())支持缓存和嵌套模板。不过这些其实都和模板本身的解析基本没关系,以后再说明这个类的实现和用途。这里我们使用 frender() 函数:
这个函数相当简单,只作了一键事情,就是读取模板文件内容,然后交给Template类处理,并且返回一个Template类实例。从这里也可以看出,整个模板的解析,只和Template类有关,frender是来打杂的。 Template类Template实例的效果当我们根据一个模板内容创建一个Template类实例t后,我们可以调用该实例,这相当于调用模板对应的
Template实例化过程Template实例化过程是把模板转换成HTML内容的实质性步骤,不过这个过程比较复杂。但是,概括的来讲,这个过程和Template的
首先把,参数里除了text以外的参数忽略掉,然后来看下对text的处理过程(text就是模板的内容)。整个过程概括的说有如下步骤:
其他没有说明的代码,暂时都可以忽略,不会影响你理解Template的实例化过程。从上面的步骤可以看出,Template实例化的过程主要有两个:生成 生成__template__()函数的代码这个是模板生成过程中最长最复杂的一段,会应用到Python的token分析功能以及动态编译功能。还记得第一篇里,我们搭建实验环境的时候,修改了web.py源码,在一个地方插入了一行打印语句么?没错,就是这个
|