将类标记为“安全”以在模板中呈现

Aco*_*orn 2 python django django-templates

我正在编写一个将由自定义模板过滤器返回的类。它有一个__str__返回 HTML 的方法。我不希望 HTML 被转义。

我尝试mark_safe在从方法返回字符串之前先调用它__str__,但结果被转义了。我假设这是因为 Django 在将对象转换为字符串之前检查该对象是否安全?

我可以以某种方式将课程本身标记为安全吗?

例如

class ParagraphTag(object):
    def __init__(self, text):
        self.text = text

    def __str__(self):
        return mark_safe('<p>{}</p>'.format(self.text + 'baz'))

@register.filter(name='paragraph_tag')
def paragraph_tag(text):
    return ParagraphTag(text)
Run Code Online (Sandbox Code Playgroud)

在模板中渲染段落标记对象会导致其被转义。

例如{{ paragraph_tag }}-><p>foo</p>

如果我在从模板过滤器返回对象时调用mark_safe对象ParagraphTag本身,那么它就会变成一个SafeBytes不是我想要的对象。我希望在我的模板中提供丰富的对象,并且仅在渲染时将其转换为字符串。

Lou*_*uis 5

Django 通常用于unicode()从 Python 对象中获取字符串。您必须实现__unicode__它才能返回安全的 Unicode 字符串。否则,将返回的默认值将从转换中获取__str__,但会变得不安全。

作为记录,这是我用来诊断它的代码:

from django.utils.html import mark_safe

class ParagraphTag(object):

    def __init__(self, text):
        self.text = text

    def __str__(self):
        return mark_safe('<p>{}</p>'.format(self.text + 'baz'))

print str(ParagraphTag("foo")).__class__
print str(ParagraphTag("foo"))
print 
print unicode(ParagraphTag("foo")).__class__
print unicode(ParagraphTag("foo"))
print mark_safe(unicode(ParagraphTag("foo"))).__class__
Run Code Online (Sandbox Code Playgroud)

这将输出:

<class 'django.utils.safestring.SafeBytes'>
<p>foobaz</p>

<type 'unicode'>
<p>foobaz</p>
<class 'django.utils.safestring.SafeText'>
Run Code Online (Sandbox Code Playgroud)

下面是一个将生成安全 Unicode 的类的示例:

class ParagraphTagFixed(object):

    def __init__(self, text):
        self.text = text

    def __str__(self):
        return unicode(self).encode("utf-8")

    def __unicode__(self):
        return mark_safe(u'<p>{}</p>'.format(self.text + u'baz'))

print unicode(ParagraphTagFixed("foo")).__class__
print unicode(ParagraphTagFixed("foo"))
print str(ParagraphTagFixed("foo")).__class__
print str(ParagraphTagFixed("foo"))
Run Code Online (Sandbox Code Playgroud)

它将显示:

<class 'django.utils.safestring.SafeText'>
<p>foobaz</p>
<class 'django.utils.safestring.SafeBytes'>
<p>foobaz</p>
Run Code Online (Sandbox Code Playgroud)