【问题标题】:Constructing Django templates from strings within Python code从 Python 代码中的字符串构造 Django 模板
【发布时间】:2018-02-21 18:55:07
【问题描述】:

我想测试我在 Django 中编写的自定义过滤器label_with_classes。我的基本方法是通过使用字符串实例化 django.template.Template 来实例化我的实际模板的“sn-p”,用一些上下文渲染它,并断言生成的输出是我所期望的。

我还希望能够像在实际模板中那样在新行上编写标签等。问题是,当我这样做时,渲染输出中会出现很多空格。

到目前为止,这是一个测试用例:

from ..templatetags.label_with_classes import label_with_classes
from django.test import SimpleTestCase
from django.template import Context, Template


from ..forms.sessions import SessionForm


class CustomFilterTest(SimpleTestCase):
    def test_1(self):
        form = SessionForm(data={})

        template = Template("\
            {% load label_with_classes %}\
            {{ form.session_number|label_with_classes }}")
        context = Context({'form': form})

        output = template.render(context)

然后我使用import ipdb; ipdb.set_trace() 进入调试器。在这里我看到output 有很多前导空格:

ipdb> output
'                        <label class="invalid" for="id_session_number">Session number:</label>'

这个空格似乎来自我在Template() 构造函数中的字符串的新行上写的。但是,在实际的 HTML 中,HTML 标记之间的空格会被忽略。

有没有办法在 Python 中“编写 HTML”,以便我可以直接将实际 HTML 模板中的 sn-ps 复制粘贴到此测试代码中?

更新

我尝试过使用textwrap.dedent(),但我仍然得到一些前导空格。使用这样构造的模板:

    template = Template(textwrap.dedent("\
        {% load label_with_classes %}\
        {{ form.session_number|label_with_classes }}"))

output 看起来像

ipdb> output
'            <label class="invalid" for="id_session_number">Session number:</label>'

虽然空格比以前少了,但它们仍然存在。

【问题讨论】:

    标签: python html django


    【解决方案1】:

    在这种情况下我喜欢使用这个小技巧:

    html = "\
        {% load label_with_classes %}\
        {{ form.session_number|label_with_classes }}"
    
    html = ' '.join(html.split())
    template = Template(html)
    

    它将删除所有空格,并且单词/标签等之间将仅包含一个空格。这与 HTML 上的预期行为非常相似(多个空格被忽略)。

    【讨论】:

      【解决方案2】:

      我最终只是在template.render() 的输出上调用strip()

      output = template.render(context).strip()
      

      这会删除前导(和尾随)空格:

      ipdb> output
      '<label class="invalid" for="id_session_number">Session number:</label>'
      

      在这种情况下,只有一个 HTML 标签 (&lt;label&gt;);如果有多个并且我想删除它们之间的空格,我还可以使用正则表达式来删除关闭 &gt; 和打开 &lt;s 之间的空格:

      import re
      output = re.sub(r'>\s*<', r'><', output)
      

      Removing spaces and newlines between tags in html (aka unformatting) in python 中所述。

      更新

      考虑到这个特殊的用例——单元测试——也可以使用 Django 的 TestCase 类的 assertHTMLEqual 方法,它根据 HTML 语义断言两个字符串相等。例如,以下测试通过:

          output = template.render(context)
          self.assertHTMLEqual(output, '<label class="invalid" for="id_session_number">Session number:</label>')
      

      即使我没有在output 上致电strip()

      【讨论】:

        猜你喜欢
        • 2015-06-28
        • 2011-10-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-27
        • 1970-01-01
        相关资源
        最近更新 更多