Шаблоны Django разделяют пробелы?

У меня возникают проблемы с шаблонами Django и моделями CharField.

Итак, у меня есть модель с CharField, которая создает пул, который заменяет пробелы символами подчеркивания. Если я создаю объект, Somename Somesurname, это создаст Slume Somename_Somesurname и будет отображаться как ожидается на шаблоне.

Однако, если я создаю объект, Somename Somesurname (обратите внимание на второе пространство), будет создан Slomen Somename__Somesurname, и хотя на консоли Django я вижу это как <Object: Somename Somesurname>, в шаблоне он отображается как Somename Somesurname.

Итак, шаблоны Django каким-то образом разделяют пробелы? Есть ли фильтр, который я могу использовать, чтобы получить имя с его пробелами?

Ответы

Ответ 1

Позвольте мне изложить это, сказав, что ответ @DNS правилен относительно того, почему пробелы не отображаются.

Учитывая это, этот шаблонный фильтр заменит любые пробелы в строке &nbsp;

Использование:

{{ "hey there  world"|spacify }}

Вывод будет hey&nbsp;there&nbsp;&nbsp;world

Вот код:

from django.template import Library
from django.template.defaultfilters import stringfilter
from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe
import re

register = Library()

@stringfilter
def spacify(value, autoescape=None):
    if autoescape:
    esc = conditional_escape
    else:
    esc = lambda x: x
    return mark_safe(re.sub('\s', '&'+'nbsp;', esc(value)))
spacify.needs_autoescape = True
register.filter(spacify)

За информацией о том, как работают фильтры шаблонов и как их установить, проверить документы.

Ответ 2

Django видит объект внутренне как имеющий два пробела (судя по двум символам подчеркивания и двум пробелам в выводе repr). Тот факт, что он отображается только с одним пробелом в шаблоне, - это то, как работает HTML. Обратите внимание, что в вопросе, который вы только что задали, в большинстве мест, где вы ввели два пробела, отображается только один?

Из Спецификация HTML4:

В частности, пользовательские агенты должны сворачивать входные последовательности белого пространства при создании межслоевого пространства вывода.

Как предложил С.Лотт, вы можете убедиться, что моя догадка верна, добавив ведение журнала отладки или используя плагин Firebug для Firefox или что-то подобное, чтобы точно узнать, что нужно отправить в браузер. Тогда вы точно поймете, в чем проблема.

Если для вас действительно важны несколько пространств, вам нужно использовать объект &nbsp;, хотя я не знаю, как вы могли бы заставить Django кодировать выходные данные этого конкретного объекта, используя их.

Ответ 3

Существует встроенный тег шаблона без пробелов

{% spaceless %}
    <p>
        <a href="foo/">Foo</a>
    </p>
{% endspaceless %}

Какие результаты:

<p><a href="foo/">Foo</a></p>

Подробнее в django документация.

Ответ 4

Slugify удаляет все ведущие пробелы, вам нужно будет переписать это как настраиваемый тег шаблона, чтобы получить поведение, которое вы после. Исходный код фильтра выглядит следующим образом:

def slugify(value):
   """
   Normalizes string, converts to lowercase, removes non-alpha characters,
   and converts spaces to hyphens.
   """
   import unicodedata
   value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
   value = unicode(re.sub('[^\w\s-]', '', value).strip().lower())
   return mark_safe(re.sub('[-\s]+', '-', value))

который изменяет "some string" на "some-string", убивая лишние пробелы. Вы можете изменить его так:

def new_slugify(value):
   """
   Normalizes string, converts to lowercase, removes non-alpha characters,
   and converts spaces to hyphens, does not remove leading whitespace.
   """
   import unicodedata
   value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
   value = unicode(re.sub('[^\w\s-]', '', value).strip().lower())
   return mark_safe(re.sub('[-\s]', '-', value))

Это приведет к следующему поведению: "Some String here" для "some-string-here"

У вас все еще могут быть проблемы, как упоминалось ранее, с тем, как html обрабатывает лишние пробелы, вам нужно написать другой фильтр deslugify.

Ответ 5

Этот тег сохраняет пробелы и символы новой строки. Я скопировал Django собственный тег linebreaksbr, а затем добавил строку для замены пробелов nbsp. Он не заменяет отдельные пробелы, поэтому текстовый источник все еще доступен для чтения. Я написал это, потому что я не мог получить тег spacify (другой ответ) для работы с linebreaksbr.

from django.template.defaultfilters import stringfilter
from django.utils.safestring import mark_safe, SafeData
from django.utils.text import normalize_newlines
from django.utils.html import escape

@register.filter(is_safe=True, needs_autoescape=True)
@stringfilter
def keep_spacing(value, autoescape=None):
    autoescape = autoescape and not isinstance(value, SafeData)
    value = normalize_newlines(value)
    if autoescape:
        value = escape(value)
    value = mark_safe(value.replace('  ', ' &nbsp;'))             
    return mark_safe(value.replace('\n', '<br />'))

Ответ 6

'\s' может быть в порядке, описанном выше, но будьте осторожны, это заменяет другие пробелы, такие как '\t' или '\n'! Если это не то, что вы хотите, просто используйте " " вместо этого.

Ответ 7

Если у вас проблемы с шаблоном django, попробуйте это: У меня была похожая проблема с моим тегом <optgorup>, я получаю свои значения из модели django для отображения при выборе. Я просто использовал '' опцию вокруг метки, чтобы получить полный текст с пробелом. <optgroup label='{{key}}'>