让我们一起来构建一个模板引擎(三)

在 上篇文章 中我们的模板引擎实现了对 iffor 对支持,同时在文章的最后我给大家留了一个 问题:如何实现支持 includeextends 的标签功能。

在本篇文章中我们将一起来动手实现这两个功能。

include

include 标签对语法是这样的:假设有一个 item.html 模板文件,它的内容如下:

1 <li>{{ item }}</li>

还有一个我们要渲染的模板 list.html 内容如下:

12345 <ul>  {% for item in items %}    {% include \”item.html\” %}  {% endfor %}</ul>

渲染 list.html 后的结果类似:

12345 <ul>  <li>item1</li>  <li>item2</li>  <li>item3</li></ul>

从上面可以看出来 include 标签的作用类似使用 include 所在位置的名字空间 渲染另一个模板然后再使用渲染后的结果。所以我们可以将 include 的模板文件 当作普通的模板文件来处理,用解析那个模板生成后的代码替换 include 所在的位置, 再将结果追加到 result_var 。 生成的代码类似:

1234567891011 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):

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 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 = []实现支持 includeextends 的标签功能。

在本篇文章中我们将一起来动手实现这两个功能。

include

include 标签对语法是这样的:假设有一个 item.html 模板文件,它的内容如下:

1 <li>{{ item }}</li>

还有一个我们要渲染的模板 list.html 内容如下:

12345 <ul>  {% for item in items %}    {% include \”item.html\” %}  {% endfor %}</ul>

渲染 list.html 后的结果类似:

12345 <ul>  <li>item1</li>  <li>item2</li>  <li>item3</li></ul>

从上面可以看出来 include 标签的作用类似使用 include 所在位置的名字空间 渲染另一个模板然后再使用渲染后的结果。所以我们可以将 include 的模板文件 当作普通的模板文件来处理,用解析那个模板生成后的代码替换 include 所在的位置, 再将结果追加到 result_var 。 生成的代码类似:

1234567891011 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):

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 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 = []