Как предотвратить автоэкранирование основных строк Django - PullRequest
3 голосов
/ 30 марта 2012

Приложение Django Basic Inlines отображает предопределенный шаблон из псевдо-HTML-синтаксиса на основе комбинации приложения / модели / идентификатора.Например, если вы пишете сообщение в блоге, вы можете вставить изображение, которое было сохранено в вашей модели изображения:

# In the admin
This is the body of my post.

<inline type="media.image" id="1" class="full">

Затем шаблон принимает фильтр render_inlines, который необходимо пометить safe, чтобы правильно отобразить HTML:

# Template
{{ post.body|render_inlines|safe }}

Но даже с safe фильтр все еще экранирует HTML, создавая &lt;p&gt;&lt;img src="..."&gt;&lt;p&gt; в источнике.

В соответствии сДокументы, фильтр должен использовать mark_safe для предотвращения автоэкранирования на уровне фильтра, но функция inlines в parser.py уже использует mark_safe.

Есть ли что-то, что еще нужно в Django 1.4 дляостановить автоэкранирование на пользовательском слое фильтра?Кажется, я не могу избавиться от этого автоэкранирования ни в функции

Я пытался использовать autoescape=None, который, похоже, тоже не помог.

Ответы [ 3 ]

1 голос
/ 03 апреля 2012

Я поддерживаю вилка приложения Inline. Ричард связался со мной по поводу этой проблемы, и я смог отследить ее до BeautifulSoup, а не Django.

Проблема заключалась в том, что метод BeautifulSoup replaceWith() использовался для замены встроенной разметки отображаемым шаблоном. Результат render_to_string() - это, конечно, строка. Когда replaceWith() получает строку, она превращается в NavigableString. Поскольку BeautifulSoup ожидает, что NavigbleString s будут строками, он предполагает, что они небезопасны, и экранирует любые символы HTML. В результате значение, возвращаемое функцией inlines() в Inline, содержало группу &gt; и &lt;, а не < и >.

Я не заметил этой проблемы в Django 1.3. Когда я посмотрел, BeautifulSoup действительно возвращал экранированный HTML. Шаблонный фильтр |safe в Django, должно быть, экранировал ранее экранированный HTML. В Django 1.4 он больше этого не делает. (И этого не должно быть!)

Мое исправление для этого - проанализировать входящее значение с BeautifulSoup и использовать BeautifulSoup, чтобы найти всю встроенную разметку, как и прежде. Вместо того, чтобы использовать метод replaceWith() BeautifulSoup для замены встроенной разметки визуализированным встроенным шаблоном, я теперь просто использую простой старый Python str.replace(). Мне немного неловко, превращая разобранный суп обратно в строку и затем заменяя ее. Но это работает. Отчасти я испытываю желание просто покончить с BeautifulSoup и найти встроенную разметку с регулярными выражениями, но мы все знаем, чем это заканчивается . Если у кого-то есть идея получше, я весь в ушах!

Исправление было изначально включено в этот коммит . Я улучшил его в следующем коммите, но, очевидно, StackOverflow позволяет мне публиковать максимум две ссылки, так что вам придется найти его самостоятельно!

1 голос
/ 13 апреля 2012

Другое решение этой проблемы - превратить новый код в объект BeautifulSoup и заменить его указанным объектом.Таким образом, красивый суп, кажется, ведет себя правильно.

Это дает вам экранированный html:

soup = BeautifulSoup(html_doc)
body = soup.body
new_html = """<p> this is some deap code</p><a href="#">Pointless even</a>"""
body.replaceWith(new_html)

Это дает вам html без ограничений:

soup = BeautifulSoup(html_doc)
body = soup.body
new_html = """<p> this is some deap code</p><a href="#">Pointless even</a>"""
body.replaceWith(BeautifulSoup(new_html))
0 голосов
/ 31 марта 2012

Это из-за render_to_string здесь . Перейдите к inlines/app_model.html и inlines/default.html и добавьте |safe после переменных содержимого там.

...