【问题标题】:How to parse Django templates for template tags如何解析模板标签的Django模板
【发布时间】:2013-03-31 13:21:29
【问题描述】:

情况

我正在编写一个检查 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)

【问题讨论】:

  • 我无法回答您的主要问题,但是要让 django 解析模板但不让它返回 http 响应,您可以使用 render_to_string 将编译后的 HTML:docs.djangoproject.com/en/1.5/ref/templates/api/…
  • 根据django book,“大部分解析都是通过调用单个正则表达式进行的”。因此,与构建真正的解析器相比,简单地从 Django 源代码中查找并导入或复制 RegEx 可能会更好。
  • 另外,你为什么不想使用正则表达式?
  • 使用 docs.djangoproject.com/en/1.5/ref/templates/api/… 解析模板并在 django shell 中编译它,然后使用 dir() 在对象上四处寻找,直到找到所需的信息。
  • There 是尝试使用正则表达式完成任务。可能对你有帮助

标签: python django


【解决方案1】:

你说...

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

...和...

我不想使用正则表达式。

...因为...

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

...但是,坦率地说,从头开始编写解析器可能比使用正则表达式更混乱。我看不出像...这样简单的正则表达式有什么乱七八糟的地方。

"{% *url +[^']"

...我怀疑是否有一个非正则表达式的解决方案会像那样简洁。

关于……

我还想检查它们是否包含 {% load url from future %} 在他们的模板中。

如果您的目的是确保 Django 1.5 的兼容性,这是没有意义的。根据Django 1.5 release notes,新式url标签语法默认开启,所以{% load url from future %}这行不会有任何作用。

在 1.5 之前的版本中,只需将...

import django.template
django.template.add_to_builtins('django.templatetags.future')

...在您的settings.py 的底部并完成它。 :-)

【讨论】:

    【解决方案2】:

    您也可以使用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

    【讨论】:

      【解决方案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

      【讨论】:

      • 我认为你写的最后一行代码有语法错误:t2 = Template("{% load url from future %}\n ... 语法错误是因为你使用了双引号,如果你使用单引号就可以了。
      • 谢谢。将该行替换为另一个示例
      猜你喜欢
      • 2015-01-20
      • 1970-01-01
      • 1970-01-01
      • 2018-10-21
      • 2014-05-23
      • 2022-11-25
      • 2015-07-25
      • 1970-01-01
      • 2011-02-09
      相关资源
      最近更新 更多