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

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

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

include

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

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

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

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

生成类似上面的代码就是 include 的关键点,下面看一下实现 include 功能 都做了哪些改动 (可以从 Github 上下载 template3a.py):

首先是 __init__ 增加了两个参数 template_direncoding:

  • template_dir: 指定模板文件夹路径,因为 include 的模板是相对路径所以需要这个 选项来获取模板的绝对路径
  • encoding: 指定模板文件的编码,默认是 utf-8

然后就是 _parse_another_template_file 了,这个方法是用来解析 include 中 指定的模板文件的,其中的 func_nameresult_var 之所以加了个 hash 值 作为后缀是不想跟其他函数变量重名。

_handle_include 实现的是解析 include 的模板, 然后将生成的代码和代码中函数的执行结果添加到当前代码中。

下面来看一下实现的效果。还是用上面的模板文件:

item.html:

list.html:

先来看一下生成的代码:

然后是渲染效果:

include 已经实现了,下面让我们一起来实现 extends 功能。

extends

extends 标签实现的是模板继承的功能,并且只能在第一行出现,语法如下:

假设有一个 parent.html 文件它的内容是:

还有一个 child.html 文件:

child.html 渲染后的结果:

可以看到 extends 的效果类似用子模板里的 block 替换父模板中定义的同名 block, 同时又可以使用 {{ block.super }} 引用父模板中定义的内容,有点类似 class 的继承效果。

注意我刚才说的是: 类似用子模板里的 block 替换父模板中定义的同名 block

这个就是 extends 的关键点,我们可以先找出子模板里定义的 block , 然后用子模板里的 block 替换父模板里的同名 block , 最后只处理替换后的父模板就可以了。

暂时先不管 block.super ,支持 extends 的代码改动如下(可以从 Github 下载 template3b.py ):

从上面的代码可以看出来我们遵循的是使用子模板 block 替换父模板同名 block 然后改为解析替换后的父模板的思路. 即,虽然我们要渲染的是:

实际上我们最终渲染的是替换后的父模板:

依旧是来看一下实际效果:

parent1.html:

child1.html:

看看最后要渲染的模板字符串:

可以看到确实是替换后的内容,再来看一下生成的代码和渲染后的效果:

extends 的基本功能就这样实现了。下面再实现一下 {{ block.super }} 功能。

block.super

{{ block.super }} 类似 Python class 里的 super 用来实现对父 block 的引用,让子模板可以重用父 block 中定义的内容。 只要改一下 _replace_parent_blocks 中的 replace 函数让它支持 {{ block.super }} 就可以了(可以从 Github 下载 template3c.py):

效果:

parent2.html:

child2.html:

到目前为主我们已经实现了现代 python 模板引擎应有的大部分功能了:

  • 变量
  • if
  • for
  • include
  • extends, block, block.super

后面需要做的工作就是完善我们代码了。

不知道大家有没有注意到,我之前都是用生成 html 来试验模板引擎的功能的, 这是因为模板引擎确实是在 web 开发中用的比较多,既然是生成 html 源码那就需要考虑 针对 html 做一点优化,比如去掉多余的空格,转义之类的,还有就是一些 Web 安全方面的考虑。

至于怎么实现这些优化项,我将在 第四篇文章 中向你详细的讲解。敬请期待。

打赏支持我写出更多好文章,谢谢!

打赏作者

打赏支持我写出更多好文章,谢谢!

1 收藏 评论

关于作者:mozillazg

好好学习,天天向上。 个人主页 · 我的文章 · 1 ·   

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部