Django - 只标记字符串/用户输入的某些部分是否安全?

时间:2014-11-19 02:19:54

标签: django django-templates django-template-filters

用户文本输入如下:

Test 'post'. Post at 8:52 on Feb 3rd. /u/username created it.
This <a href="link">link</a> should not be displayed as a link.

我在模板上显示时,通过自定义过滤器发送用户的输入。这是自定义过滤器:

word_split_re = re.compile(r'(\s+)')

@register.filter
@stringfilter
def customUrlize(value):
    words = word_split_re.split(force_text(value))
    for i, b in enumerate(words):
        if b.startswith('/u/'):
            username = b[3:]
            if re.match("^[A-Za-z0-9_-]*$", username):
                b = "<a href='testLink'>" + b + "</a>"
                words[i] = mark_safe(b)
    return ''.join(words)

正如你所看到的,我想要做的是包装以&#39; / u /&#39;开头的单词。 (并且只包含字母,数字,下划线和短划线)和

<a>

标签。使用当前过滤器,所有代码都将被转义,并显示为:

Test 'post'. Post at 8:52 on Feb 3rd. <a href='testLink'>/u/username</a> created it.
This <a href="link">link</a> should not be displayed as a link.

我想要的是正常显示文本,但/ u / username是链接。

如果我尝试:

return mark_safe(''.join(words))

然后它甚至显示

<a href="link">link</a>

一起作为链接
/u/username

如何制作它只显示

/u/username

作为链接?

编辑:我正在使用Django 1.5。

在我的模板中,假设

comment

CharField

我将评论显示为:

{{ comment|customUrlize }}

2 个答案:

答案 0 :(得分:3)

除非您希望保留文本中的其他格式,否则您可以在更改之前escape文本。

  

返回给定的文本,其中包含编码用于HTML的&符号,引号和尖括号。输入首先通过force_text(),输出已应用mark_safe()

     

From the Django documentation

所以这一行:

words = word_split_re.split(force_text(value))

成为这个:

words = word_split_re.split(escape(value))

完整的过滤器是:

from django.utils.html import escape

word_split_re = re.compile(r'(\s+)')

@register.filter
@stringfilter
def customUrlize(value):
    words = word_split_re.split(escape(value)) 
    for i, b in enumerate(words):
        if b.startswith('/u/'):
            username = b[3:]
            if re.match("^[A-Za-z0-9_-]*$", username):
                b = "<a href='testLink'>" + b + "</a>"
                words[i] = mark_safe(b)
    return mark_safe(''.join(words))

应该给:

Test 'post'. Post at 8:52 on Feb 3rd. <a href='testLink'>/u/username</a> created it.
This &lt;a href="link"&gt;link&lt;/a&gt; should not be displayed as a link.

呈现为:

  

测试&#39;发布&#39;。发布于2月3日8:52。 /u/username创建了它。   这&lt; a href =&#34;链接&#34;&gt;链接&lt; / a&gt;不应显示为链接。

答案 1 :(得分:1)

根据您的需要,它可能无济于事,但您可以将字符串拆分为两个,而在模板中只标记第一个带有| safe的字符串。

例如:

a = "Test 'post'. Post at 8:52 on Feb 3rd. <a href='testLink'>/u/username</a> created it. This <a href='link'>link</a> should not be displayed as a link."

b = a.split('it.')

然后将其作为

传递给模板
'string1': b[0]
'string2': b[1]

或其他任何内容,然后是模板中的{{string1|safe}} <br> {{string2}}

输出将如您所愿。没有“它。”,当然。但这很容易解决。