0

我正在编写一个应用程序来跟踪 2 名玩家之间的一系列比赛。我正在使用 Django 的User模型并用我自己的UserProfile.

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

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

问题

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

实际错误

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

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

模板/梯子/match_game_listing.html

{{ match.challengee|steam_name }}

match.challengee这种情况下是76561197971597000

梯子/模板标签/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 无法对位置 16 中的字符 u'\u260e' 进行编码:序数不在范围内(128)

有一个有用的提示:

Unicode 错误提示

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

我已经尝试过无数次浏览 Django 文档,但我尝试过玩force_text()但无济于事,但由于我有点不清楚为什么这不起作用,我可能只是错过了相关部分。此模板标签适用于名称没有 unicode 的情况。

4

2 回答 2

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总是str和的输出unicode.format总是unicode。通过这种方式,它与旧%运算符不同,其中str % unicode -> unicode.

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

return mark_safe(steam_string)

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

"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))
于 2013-09-18T08:29:23.183 回答
3

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

就像是:

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

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

从阅读本文中得到:https ://docs.djangoproject.com/en/dev/ref/unicode/

于 2013-09-18T02:05:37.173 回答