Шаблоны Django и пробелы
я начал использовать custom включение теги в моих шаблонах django. Например у меня есть {% profilelink profile %}
тег, который вставляет ссылку на профиль пользователя вместе с небольшой версией изображения профиля, например (profilelink.HTML-код):
<a href='{% url ... %}'><img src='{{ ... }}' alt='...'> {{ profile.name }}</a>
однако, когда я использую его в следующем фрагменте (sometemplate.HTML-код):
<p>Owned by {% profilelink owner %} (uploaded by {% profilelink uploader %})</p>
затем я получаю пробелы между HTML, созданными вторым тегом шаблона и закрывающая круглая скобка. этот пробел нежелателен. Он исходит из последнего символа новой строки в файле profilelink.HTML-код. Это очень распространенная проблема, и поиск Stackoverflow дает много вопросов о пробелах в шаблонах в целом. Вот резюме решений, найденных до сих пор, и почему они не работают:
некоторые из этих проблем решаемы с {% spaceless %}
- тег, но не все из них. Этот тег удаляет только пробелы между теги, чего нет в приведенном выше примере.
одним из возможных решений является отсутствие окончательного EOL в profilelink.HTML-код но это крайне нежелательно. Причины: это, как правило, плохой стиль; некоторые редакторы (vim) молча добавляют его по умолчанию; вот как POSIX определяет строку; он может сделать некоторые СДМ несчастным; и т. д.
другое решение переключается на другой движок шаблонов, например Jinja2, что может решить или не решить эту проблему. Он поддерживает такие конструкции, как {% ... -%}
которые едят следующий символ EOL. Это полезно в некоторых ситуациях, но также бесполезно для моего примера выше. Но переключение бэкэнда шаблонов для такого небольшого раздражения кажется немного излишним и добавляет еще одну зависимость. Я хотел бы придерживаться того, что является стандартным способом "Джанго". Однако, по-видимому, есть планы сделать Jinja2 новым дефолтом Django.
некоторые люди рекомендуется использовать класс промежуточного программного обеспечения для удаления избыточных пробелов из сгенерированного HTML перед его отправкой в браузер. Это полезно, но только для преобразования HTML функционально эквивалентным образом, т. е. той же семантики: он будет отображаться таким же образом в браузере. Это не то, что я хочу, я хочу фактическое изменение семантики, чтобы она отображалась правильно. Это невозможно реализовать в универсальном промежуточном классе. Мне нужен контроль. это на индивидуальной основе самого шаблона. Я не забочусь о том, чтобы сделать HTML красивее, я забочусь о том, чтобы он был правильным в первую очередь.
там же ошибка #2594 который был закрыт как WONTFIX с аргументом (цитата) "язык шаблонов Django достаточно хорош для генерации HTML, который не чувствителен к пробелам". В моем oponion это совершенно неправильно. HTML очень чувствителен к пробелам, он просто не важно, сколько их там. Он очень заботится о том, есть ли пробелы или нет.
некоторые мой вопрос: есть ли какой-либо разумный способ решить эту проблему в целом? (Тот, который всегда работает, а не только в некоторых ситуациях.)
(любые исправления на основе CSS не учитываются. Копировать / вставлять сюрпризы-это зло.)
2 ответов
Я считаю, что одним из решений является использование simple_tag
вместо тега включения, надеюсь, без большого беспорядка.
Я предполагаю, что ваш тег что-то вроде этого:
@register.inclusion_tag('profilelink.html')
def profilelink(user):
return {"profile": user}
можно ли было бы заменить это на
from django.template.loader import render_to_string
@register.simple_tag
def profilelink(user):
t = render_to_string("profilelink.html", {"profile": user})
return t.strip()
у меня сейчас нет Джанго-проекта передо мной, так что это непроверено.
Это лучшее, что я придумал до сих пор. Я все еще надеюсь на лучшее решение, но пока это будет сделано.
Я определил пользовательский фильтр, как это в база / templatetags / basetags.yp (из этого ответа):
from django import template
from django.template.defaultfilters import stringfilter
register = template.Library()
@register.filter
@stringfilter
def trim(value):
return value.strip()
а затем используйте его следующим образом:
{% load basetags %}
<p>Owned by {% profilelink owner %} (uploaded by
{% filter trim %}{% profilelink uploader %}{% endfilter %})</p>