如何解析模板标签的Django模板

时间:2013-04-09 07:58:13

标签: python django

情况

我正在编写一个检查Django模板的检查程序。例如,我想检查是否所有使用url模板标签的Django模板,在第一个参数上使用引号,以便它与Django 1.5兼容。另外,我想检查一下他们的模板中是否包含{% load url from future %}

例如,如果我的程序解析以下Django模板,我希望它引发异常。

{% extends 'base.html' %}
<td>
  <a href="{% url first second %}">
  </a>
</td>

但是这个模板应该毫无例外地进行解析。

{% extends 'base.html' %}
{% load url from future %}
<td>
  <a href="{% url 'first' second %}">
  </a>
</td>

我不仅限于这个简单的例子。我还有其他解析方法。例如,我想检查模板中存在多少个load模板标记。

问题

如何优雅地解决此解析问题?

  • 我不想使用正则表达式。
  • 我这个Django它自己在这方面有一些实用工具。我认为使用它们是一个好主意,但我不知道如何。
  • 我想从Django中独立运行程序。所以我不希望Django自己运行程序(使用render_to_response)。 (这很重要

代码

请给我一些可以解决我提到的例子的代码。我想检测代码中是否有{% load url from future %}。另外,我想检查每个url模板标签,并检查是否引用了第一个参数。

加成

  • 我希望能够看到Django从这个模板生成的渲染HTML,并对其进行HTML解析。 (例如使用PyQuery)

3 个答案:

答案 0 :(得分:9)

你说......

  

我想检查是否所有使用url的Django模板   模板标签,在第一个参数上使用引号,以便它   Django 1.5兼容。

...和...

  

我不想使用正则表达式。

...,因为...

  

结果可能会成为一个巨大的意大利面条代码

...但是,坦率地说,从头开始编写解析器可能比使用正则表达式更麻烦。我不认为正则表达式如此简单,就像......一样简单......

"{% *url +[^']"

...我怀疑有一种非正则表达式的解决方案就像那样简洁。

关于......

  

另外我想检查一下他们是否包括在内   <{1}}在他们的模板中。

如果您的目的是确保Django 1.5的兼容性,那么这是毫无意义的。根据{{​​3}},默认情况下会启用新式url标记语法,因此行{% load url from future %}不会产生任何影响。

在1.5之前的版本中,只需放置......就简单得多了。

{% load url from future %}

...在import django.template django.template.add_to_builtins('django.templatetags.future') 的底部,并完成它。 : - )

答案 1 :(得分:4)

您还可以使用compile_string方法。

 >>> from django.template.base import *
 >>> settings.configure()
 >>> compile_string("<a href='ab'></a>{% cycle 'row1' 'row2' as rowcolors %}", None)
 >>> [<Text Node: '<a href='ab'></a>'>, <django.template.defaulttags.CycleNode object at 0x10511b210>]

编译字符串方法由Template类使用,是用于生成节点列表的方法。 在Django 1.8 Alpha中测试过。

https://github.com/django/django/blob/1f8bb95cc2286a882e0f7a4692f77b285d811d11/django/template/base.py

答案 2 :(得分:3)

下一代码仍然使用django,但它可以检查语法是否正确:

>>> from django.template import Template
>>> from django.template.defaulttags import URLNode
>>> t = Template("{% load url from future %}\n{% url projects_list company.slug %}")
>>> for node in t.nodelist:
...     if isinstance(node, URLNode):
...         for arg in node.args: print(arg)
... 
company.slug
>>> t2 = Template('{% load url from future %}\n{% url "projects_list" company.slug }')
>>> for node in t2.nodelist:
...     print(node)
... 
<django.template.defaulttags.LoadNode object at 0x32145d0>
<Text Node: '
{% url "projects_list" c'>
>>> 

如您所见,最后一个节点不是URLNode