无法获取django模板标签返回unicode

时间:2013-09-18 01:16:56

标签: python django unicode django-templates

我正在编写一款应用程序,可跟踪2名玩家之间的一系列比赛。我正在使用Django的User模型并使用我自己的UserProfile进行扩展。

我将用户名存储在User中作为他们的steamID(例如:76561197965801299),然后在登录时查找他们的用户名,并更新UserProfile

我不想查看76561197965801299,而是想查看用户名,在一个页面上,我想用更多好东西装饰这个用户名,所以我写了一个模板标签。

问题

我似乎无法从模板标签中打印unicode数据。

实际错误

  

'ascii'编解码器无法对位置16中的字符u'\ u260e'进行编码:序数   不在范围内(128)

通常Django不会因为unicode问题而烦恼(例如:我可以在管理页面中看到这个unicode对象没问题)但我从未尝试过应用模板标签,所以显然我正在做的事情这里错了。

模板/梯/ match_game_listing.html

{{ match.challengee|steam_name }}

在这种情况下,match.challengee76561197971597000

梯/ templatetags / ladder_filters.py

from django import template
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.utils.html import mark_safe
from cafe.models import UserProfile

register = template.Library()

@register.filter()
def steam_name(name):
    try:
        user_obj = User.objects.get(username=name)
        user_prof = UserProfile.objects.get(user_id=user_obj.id)

        url = user_prof.url
        handle = unicode(user_prof.handle)
        avatar = user_prof.avatar

        steam_string = "<a href='{0}' alt='{1}\'s profile'><img src='{2}' alt='{1}\'s avatar' >{1}</a>".format(url, handle, avatar)

        return mark_safe(steam_string)

    # Non-steam entities can exist, ignore
    except ObjectDoesNotExist:
        return name

当我在浏览器中查看此内容时,我收到上述错误:

  

/ ladder / dota2 /'ascii'编解码器中的UnicodeEncodeError无法编码   字符u'\ u260e'在位置16:序数不在范围内(128)

有用的暗示:

  

Unicode错误提示

     

无法编码/解码的字符串是:oose☎

我曾多次尝试浏览Django文档,我尝试使用force_text()无效,但由于我有点不清楚为什么这不起作用,我可能会失踪相关部分。此模板标记适用于名称没有unicode的情况。

2 个答案:

答案 0 :(得分:5)

steam_string = "<a href='{0}' alt='{1}\'s profile'><img src='{2}' alt='{1}\'s avatar' >{1}</a>".format(url, handle, avatar)

.format()方法不会将格式字符串从字节提升为unicode,因为格式化参数中有unicode字符串。 str.format的输出始终为strunicode.format的输出始终为unicode。这样,它与旧的%运算符不同,其中str % unicode -> unicode

由于您需要Unicode输出,因此您的格式字符串也必须是Unicode(u""字符串)。此外,

return mark_safe(steam_string)

为什么要标记这个安全?事实并非如此。如果没有HTML转义,格式化参数中的任何HTML特殊字符都可能导致HTML注入漏洞导致XSS攻击。你的撇号也是错误的:

"alt='{1}\'s profile'"

\'是一个Python字符串文字转义;你将返回字符串:

alt='someone's profile'

这意味着您永远不会看到's profile后缀,因为它不属于属性值。

推荐:

from django.utils.html import escape
...
return mark_safe(
    u'<a href="{0}" alt="{1}\'s profile">'
        u'<img src="{2}" alt="{1}\'s avatar">{1}'
    u'</a>'
).format(escape(url), escape(handle), escape(avatar))

答案 1 :(得分:3)

我可能会非常简单地以错误的方式思考这个问题,但是,如果你只是通过在字符串前加上字母'u'来告诉django它是一个unicode。

类似的东西:

unicodeString = "ís"
string = u"this -> %s my unicode string" % unicodeString

如果我根本不理解你的问题,我很抱歉。 (我无法发表评论,所以我发布了答案)

阅读此内容:https://docs.djangoproject.com/en/dev/ref/unicode/