从Django模板中删除换行符

时间:2015-11-02 13:59:41

标签: django django-templates

我在这样的模板中有一个循环

{% spaceless %}
{% for lang_code, lang_name in LANGUAGES %}
    <link hreflang={{ lang_code }} href="http://example.com/
    {% if lang_code|length > 2 %}
        {{ some_path }}
    {% else %}
        {{ other_path }}
    {% endif %}
    ">
{% endfor %}
{% endspaceless %}

哪种产生类似的东西

<link hreflang="en-gb" href="http://example.com/
    some_path/ 
    "><link hreflang="de" ...>

是否可以重写这段代码,以便将整个标记写成一行?

<link hreflang="en-gb" href="http://example.com/some_path/">
<link hreflang="de" href="http://example.com/other_path/">
...

P.S。如果if / else子句被拉伸超过一行,但是该行变得不可读,则可以实现这一点。

5 个答案:

答案 0 :(得分:7)

我需要相同的,因为我使用模板生成电子邮件主题行(非HTML,因此{% spaceless %}无用)。就我而言,模板已经采用了很多不同的案例,所有内容都必须用大约500个字符写成一行。

所以在{% spaceless %}的心态中,我写了自己的{% linebreakless %}

import six
from django import template
from django.template.base import Node
from django.utils.functional import allow_lazy


register = template.Library()


@register.tag
def linebreakless(parser, token):
    nodelist = parser.parse(('endlinebreakless',))
    parser.delete_first_token()
    return LinebreaklessNode(nodelist)


class LinebreaklessNode(Node):
    def __init__(self, nodelist):
        self.nodelist = nodelist

    def render(self, context):
        strip_line_breaks = allow_lazy(lambda x: x.replace('\n', ''), six.text_type)
        return strip_line_breaks(self.nodelist.render(context).strip())

请注意,它(故意!)会保留除换行符之外的所有空格

电子邮件模板的示例用法如下所示,假设上述内容已加载到名为linebreakless.py的模板标记模块中:

{% load linebreakless %}{% linebreakless %}

{# Email subjects are (encoded) text, not HTML, so we don't need any autoescaping! #}
{% autoescape off %}

New Notification
 •
{% if flag %}
 about this
{% else %}
 about that
{% endif %}
!

{% endautoescape %}
{% endlinebreakless %}

请注意,{% linebreakless %}标记必须位于第一行(以及{% load %}指令之后),以防止生成的文件中出现任何换行符。

答案 1 :(得分:4)

spaceless标记会删除html标记之间的空格,因此您无法像标记一样删除标记内的空格。

您可以通过将if / else子句放在一行来阻止换行,但正如您所说,这使得难以阅读。这告诉我你正在尝试在Django模板中做太多的工作,并且url应该在其他地方构建。

最简单的选择是在视图中构建(language_code, url)标记列表,并在模板中循环显示这些标记。

{% for lang_code, url in language_urls %}
    <link hreflang={{ lang_code }} href="{{ url }}">
{% endfor %}

如果在视图中执行此操作不方便,则可以选择以下几个选项:

  • 模板上下文处理器(如果您在每个视图中使用相同的网址,则很好
  • 自定义模板标记/过滤条件(如果some_pathother_path是动态的,则很好)

答案 2 :(得分:1)

一种替代方法是使用Jinja2模板,Django从1.8开始支持该模板。来自Jinja2's documentation on whitespace control

  

如果您在块的开头或结尾(例如For标记),注释或变量表达式中添加减号(-),则该块之前或之后的空格将被删除:

{% for item in seq -%}
    {{ item }}
{%- endfor %}

将模板从Django转换为Jinja2并不完全简单。不过,如果您使用模板来构建文本文件而不是HTML文件,那么这可能是值得的。

答案 3 :(得分:0)

如果您只想删除由于
标签而引起的下一行,则只需使用-

{{value|striptags}}

这将删除标记,并且输出将简单,自由(也包括换行)。希望它能工作:)

答案 4 :(得分:0)

我需要它并更新了@Henrik的答案以与keep_lazy一起使用

 @register.tag
 def linebreakless(parser, token):
     nodelist = parser.parse(('endlinebreakless',))
     parser.delete_first_token()
     return LinebreaklessNode(nodelist)


 class LinebreaklessNode(Node):
     def __init__(self, nodelist):
         self.nodelist = nodelist

     def render(self, context):
         strip_line_breaks = keep_lazy(six.text_type)(lambda x: x.replace('\n\n', '\n'))

         return strip_line_breaks(self.nodelist.render(context).strip())