Django - 仅将字符串/用户输入的某些部分标记为安全?
Posted
技术标签:
【中文标题】Django - 仅将字符串/用户输入的某些部分标记为安全?【英文标题】:Django - mark only certain part of string / user input as safe? 【发布时间】:2015-01-16 10:32:00 【问题描述】:用户文本输入如下:
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)
如您所见,我想要做的是以 '/u/' 开头的单词(并且只包含字母、数字、下划线和破折号)用
<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
【问题讨论】:
【参考方案1】:除非您要保留文本中的某些其他格式,否则您可以在更改文本之前直接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 <a href="link">link</a> should not be displayed as a link.
呈现为:
测试“发布”。 2 月 3 日 8 点 52 分发帖。 /u/username 创建了它。 此链接不应显示为链接。
【讨论】:
hm,您能否再次确认您显示的呈现文本正是它为您呈现的内容?我复制粘贴了您的过滤器,但对我来说,它仍然呈现“/u/username”而不是实际链接。即使在应用了我的自定义过滤器之后,似乎 Django 也会自动转义文本。如果有帮助,我正在使用 Django 1.5。 这就是应该呈现的,我不明白这个问题。如果它没有转义<
它是否按预期工作?
渲染的文本对我来说如下所示:“测试'post'。2 月 3 日 8:52 发布。/u/username 创建了它. 此 <a href="link">link</a> 不应显示为链接。"我希望将“/u/username”呈现为实际链接,而不是在 html 中显示“”。我说的现在更有意义了吗?
另外,对不起,当我说“它仍然呈现“/u/username”时,我在最初的评论中的意思是“它仍然会呈现作为“/u/username”
远程也不行。听起来它正在显示一个链接。【参考方案2】:
根据您的需要,这可能无济于事,但您可以将字符串一分为二,并在模板中只用 |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
。
输出将如您所愿。没有“它”,当然。但这很容易解决。
【讨论】:
以上是关于Django - 仅将字符串/用户输入的某些部分标记为安全?的主要内容,如果未能解决你的问题,请参考以下文章