Удаление разрывов строк из шаблона Django

У меня есть цикл в шаблоне, подобный этому

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

Что производит что-то вроде этого

<link hreflang="en-gb" href="#" onclick="location.href='http://example.com/
    some_path/ 
    '; return false;"><link hreflang="de" ...>

Можно ли перезаписать этот код так, чтобы весь тег был написан в одной строке?

<link hreflang="en-gb" href="#" onclick="location.href='http://example.com/some_path/'; return false;">
<link hreflang="de" href="#" onclick="location.href='http://example.com/other_path/'; return false;">
...

P.S. Это может быть достигнуто, если предложение if/else растянуто на одну строку, но тогда строка становится нечитаемой.

Ответ 1

Тег spaceless удаляет пробелы между тегами html, что невозможно сделать для удаления пробелов внутри тегов, как вы пытаетесь сделать.

Вы можете предотвратить появление новых строк, поставив предложение if/else на одну строку, но, как вы говорите, это затрудняет чтение. Это говорит мне о том, что вы пытаетесь сделать слишком много работы в шаблонах Django и что URL-адреса должны быть построены еще где.

Самый простой вариант - создать список тегов (language_code, url) в представлении и пропустить их в шаблоне.

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

Если это не удобно сделать в представлении, еще пара опций:

  • обработчик контекста шаблона (хорошо, если вы используете одни и те же URL-адреса в каждом представлении
  • собственный тег/фильтр шаблона (хорошо, если some_path и other_path являются динамическими)

Ответ 2

Мне нужно то же самое, потому что я использую шаблон для генерации строки темы сообщения (не 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 %}), чтобы предотвратить разрывы строк в сгенерированном файле.

Ответ 3

Альтернативой является использование шаблона Jinja2, который поддерживает Django начиная с версии 1.8. Из документации Jinja2 по управлению пробелами:

Если вы добавите знак минуса (-) в начало или конец блока (например, для тега), комментария или выражения переменной, пробелы до или после этого блока будут удалены:

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

Преобразование шаблона из Django в Jinja2 не совсем просто. Возможно, это того стоит, если вы используете шаблон для создания текстового файла, а не файла HTML.