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

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


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

if … elif … else … endif

首先我们来实现对 if 语句的支持。 if 语句的语法如下:

我们首先要做的跟之前一样,那就是确定匹配标签语法的正则表达式。这里我们用的是下面 的正则来匹配标签语法:

然后就是生成代码了, if 语句跟之前的变量不一样那就是:需要进行缩进切换,这一点需要注意一下。

下面我们来看一下为了支持 if 标签增加了哪些代码吧(完整代码可以从 Github 上下载 template2a.py ):

上面代码的关键点是生成代码时的缩进控制:

  • 在遇到 if 的时候, 需要在 if 这一行之后将缩进往前移一步
  • 在遇到 elifelse 的时候, 需要将缩进先往后移一步,待 elif/ else 那一行完成后还需要把缩进再移回来
  • 在遇到 endif 的时候, 我们知道此时 if 语句已经结束了,需要把缩进往后移一步, 离开 if 语句的主体部分

我们来看一下生成的代码:

代码中的 if 语句和缩进没有问题。下面再看一下 render 的结果:

if 语句的支持就这样实现了。有了这次经验下面让我们一起来实现对 for 循环的支持吧。

for … endfor

模板中的 for 循环的语法如下:

从语法上可以看出来跟 if 语句是很相似了,甚至比 if 语句还要简单。只需在原有 if 语句代码 的基础上稍作修改就可以(完整版可以从 Github 上下载 template2b.py ):

可以看到其实就是修改了两行代码。按照惯例我们先来看一下生成的代码:

render 效果:

for ... endfor 语法就这样实现了。是不是很简单😄?但是还没完😁

相信大家都知道在 python 中 for 循环其实还支持 breakelse 。 下面我们就一起来让我们的模板引擎的 for 语法支持 breakelse (可以从 Github 上下载: template2c.py

可以看到,其实也是只增加了两行代码。效果:

就这样我们的模板引擎对 for 的支持算是比较完善了。 至于生成的代码里的换行和空格暂时先不管,留待之后优化代码的时候再处理。

重构

我们的 Template._parse_text 方法代码随着功能的增加已经变成下面这样了:

有什么问题呢?问题就是 for 循环里的代码太长了,我们需要分割 for 循环里的 代码。比如把对变量,if/for 的处理封装到单独的方法里。

下面展示了一种方法(可以从 Github 下载 template2d.py ):

这样处理后是不是比之前那个都放在 _parse_text 方法里要好很多?

至此,我们的模板引擎已经支持了如下语法:

  • 变量: {{ variable }}
  • 注释: {# comment #}
  • if 语句: {% if ... %} ... {% elif ... %} ... {% else %} ... {% endif %}
  • for 循环: {% for ... in ... %} ... {% break %} ... {% else %} ... {% endfor %}

之后的文章还将实现其他实用的模板语法,比如 include, extends 模板继承等。

include 的语法(item.html 是个独立的模板文件, list.html 中 include item.html):

list.html 渲染后将生成类似下面这样的字符串:

extends 的语法(base.html 是基础模板, child.html 继承 base.html 然后重新定义 base.html 中定义过的 block):

child.html:

child.html 渲染后将生成类似下面这样的字符串:

那么,该如何实现 includeextends 功能呢? 我将在 第三篇文章 中向你详细的讲解。敬请期待。

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

打赏作者

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

1 1 收藏 评论

关于作者:mozillazg

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

相关文章

可能感兴趣的话题



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