在 上篇文章 中我们的模板引擎实现了对 if
和 for
对支持,同时在文章的最后我给大家留了一个 问题:如何实现支持 include
和 extends
的标签功能。
在本篇文章中我们将一起来动手实现这两个功能。
include
include
标签对语法是这样的:假设有一个 item.html 模板文件,它的内容如下:
1 |
<li>{{ item }}</li> |
还有一个我们要渲染的模板 list.html 内容如下:
1 2 3 4 5 |
<ul> {% for item in items %} {% include "item.html" %} {% endfor %} </ul> |
渲染 list.html 后的结果类似:
1 2 3 4 5 |
<ul> <li>item1</li> <li>item2</li> <li>item3</li> </ul> |
从上面可以看出来 include
标签的作用类似使用 include
所在位置的名字空间 渲染另一个模板然后再使用渲染后的结果。所以我们可以将 include
的模板文件 当作普通的模板文件来处理,用解析那个模板生成后的代码替换 include
所在的位置, 再将结果追加到 result_var
。 生成的代码类似:
1 2 3 4 5 6 7 8 9 10 11 |
def func_name(): result = [] # 解析 include 的模板 def func_name_include(): result_include = [] return ''.join(result_include) # 调用生成的 func_name_include 函数获取渲染结果 result.append(func_name_include()) return ''.join(result) |
生成类似上面的代码就是 include
的关键点,下面看一下实现 include
功能 都做了哪些改动 (可以从 Github 上下载 template3a.py):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
class Template: def __init__(self, ..., template_dir='', encoding='utf-8'): # ... self.template_dir = template_dir self.encoding = encoding # ... def _handle_tag(self, token): """处理标签""" # ... tag_name = tag.split()[0] if tag_name == 'include': self._handle_include(tag) else: self._handle_statement(tag) def _handle_include(self, tag): filename = tag.split()[1].strip('"\'') included_template = self._parse_another_template_file(filename) # 把解析 include 模板后得到的代码加入当前代码中 # def __func_name(): # __result = [] class="crayon-o">: # __result = [] 实现支持 include 和 extends 的标签功能。
在本篇文章中我们将一起来动手实现这两个功能。 include
还有一个我们要渲染的模板 list.html 内容如下:
渲染 list.html 后的结果类似:
从上面可以看出来
生成类似上面的代码就是
|