How are django templates parsed?
我一直在尝试了解更多关于Django的模板引擎,因为它在我看来总是有点像一个黑匣子。文档对所涉及的一般步骤给出了一个很好的概述,并指出模板是被加载和解析的,从而创建了一个节点树(层叠?)并附加在一起以给出结果。
我不理解的是解析的方法,以及在什么条件下创建节点?解析后,什么构成了一个特定的节点,这对创建自定义模板标记有何影响(即,是否有更好、更有效的方法来编写模板标记,从而减少节点?).
从每个标记中创建一个节点。通过阅读如何编写自定义标记,您可以了解它是如何工作的。标签中的任何内容都将是其子项。以下是来自Django Docs的注释标记示例:
1 2 3 4 | def do_comment(parser, token): nodelist = parser.parse(('endcomment',)) parser.delete_first_token() return CommentNode() |
正如您所看到的,comment标签将解析所有内容,直到"endcomment"结束,并将其丢弃。其他标签会将
呈现是递归完成的。当在节点上调用render()时,它会在其子节点上运行render,依此类推。
解析也是递归进行的,这就是为什么你可以得到嵌套的标签,并且
节点中的上下文对象是一种dicts结构列表。额外的上下文被推到现有上下文的顶部,并传递给子节点,并在节点呈现后弹出,这样它就不会影响上部作用域。
对于没有子代的标记,不使用
了解该过程更多信息的一种方法是使用werkzeug调试器运行django,并在模板中触发异常。这样,您就可以查看(和交互)到该点为止的整个堆栈。
我想你首先应该看看code.djangoproject.com使用django/template/base.py-第一个(如Yuji Tomita之前所述)。或者下载源代码,并使用您最喜欢的编辑器或IDE进行查看。
我猜他们使用标记化和解析
一个简单的描述方法是:
Tokenizing:将代码分解为以下类型:
1 | integer foo ="bar" + 15; |
这包括
1 | T_VARIABLETYPE + T_VARIABLENAME + T_EQUALS + T_STRING + T_PLUS + T_DIGIT + T_SEMI |
在这之后,您可以通过使用解析器查找模式来进行解析。
解析:
找到模式:
1 | T_VARIABLETYPE + T_VARIABLENAME + T_EQUALS + {A recursive thing} + T_SEMI |
这样就可以执行命令
如果你想试验一下,我建议你使用"antlr"http://www.antlr.org。/它可以在很多不同的语言中使用,如Java或C语言,甚至PHP和JS。