如何在新的 Django 消息框架中输出消息中的 HTML?

我试图在通过新的 Django 消息框架显示的消息中显示一些 html。具体来说,我是通过 ModelAdmin.message _ user 方法完成这项工作的,该方法只是消息()的一个瘦包装器:

def message_user(self, request, message):
"""
Send a message to the user. The default implementation
posts a message using the django.contrib.messages backend.
"""
messages.info(request, message)

到目前为止,我所尝试的一切似乎都显示了转义的 HTML。

self.message_user(request, "<a href=\"http://www.google.com\">Here's google!</a>")

不起作用,也不起作用:

from django.utils.safestring import mark_safe
...
self.message_user(request, mark_safe("<a href=\"http://www.google.com\">Here's google!</a>"))

在 admin base.html 模板中显示模板代码非常简单:

    {% if messages %}
<ul class="messagelist">{% for message in messages %}<li>{{ message }}</li>{% endfor %}</ul>
{% endif %}

所以我不知道自己哪里做错了。

非常感谢您的思考或指导,谢谢!

28830 次浏览

你试过 \{\{ message | safe }}吗?

在 Django 模板系统模板变量是 一直都是转义的,除非您用 safe过滤器指定它们为安全的。这个默认值使得即使是不知情的人也可以免受注入攻击。

我不确定这和 mark _ safe 有什么关系,但是也许在这两者之间发生了什么让它再次变得不安全。

我正在寻找一种在管理清单中使用未转义 HTML 的方法。不确定这是否适用于消息框架,但是使用这里描述的 allow _ tag 帮助了我。

Http://urlencode.blogspot.com/2009/10/neat-django-admin-tricks-part-1.html

如下面的 Django 票据所示,如果您将 mark _ safe ()与 SessionStorage 后端结合使用,那么它应该可以工作: https://code.djangoproject.com/ticket/14976#comment:9

另一种选择是使用 extra_tags关键字 arg 来指示消息是安全的

messages.error(request, 'Here is a <a href="/">link</a>', extra_tags='safe')

然后使用模板逻辑来使用安全过滤器

{% for message in messages %}
<li class="\{\{ message.tags }}">
{% if 'safe' in message.tags %}\{\{ message|safe }}{% else %}\{\{ message }}{% endif %}
</li>
{% endfor %}

这对我很有用(Django 1.11) :

from django.contrib import messages
from django.utils.safestring import mark_safe


messages.info(request, mark_safe('This is link to <a href="http://google.com">http://google.com</a>'))

模板系统的全部要点就是像这样处理字符串和数据。

虽然每个其他的答案都指示您将构建的字符串标记为安全的,但是我会更进一步告诉您永远不要在代码中使用 HTML ——总是使用模板代替。

模板系统确保事情被正确地转义,这样你就不必担心它,而且对于程序员来说,很难进入这样的情况,他们正在构建一个 HTML 字符串从一堆 if和用户数据。

返回文章页面

<a href="https://www.google.com">Here's Google!</a>

返回文章页面

from django.template import loader


...


def view(request):
messages.info(
request,
loader.render_to_string(
'app/fragments/google_link.html',
{},
request=request,
),
)

可以使用 Format _ html。它将转义应用于所有参数。

例如,如果我们可以使用属性调用‘ name’来链接“ mymodel”细节:

from django.contrib import messages
from django.utils.html import format_html




message = format_html("{} <a href='{}'>{}</a>",
"This is the mymodel",
reverse('myapp:mymodel-detail', args=(mymodel.id,)),
mymodel.name)
messages.info(request, message)

这个答案是基于 https://stackoverflow.com/a/33751717/3816639

正如瑞安 · 卡斯克所说,正确的方法是使用 \{\{ message.message }}而不是 \{\{ message }}

{% if messages %}
<ul class="messagelist">
{% for message in messages %}
<li>\{\{ message.message }}</li>
{% endfor %}
</ul>
{% endif %}