2010-11-06 80 views
1

我正在研究一个新的Django站点,并且在一堆数据中迁移后,已经开始运行到令人深感沮丧的DjangoUnicodeDecodeError。这个坏字是一个\ xe8(e-grave)。Django字符编码

有两个沾满面糊的问题:

它只发生在生产服务器上,运行Apache的门前FCGI过程(运行与Django的开发服务器上的同一个数据库相同的代码已经没有任何问题)

有问题的堆栈跟踪完全在Django代码中。它在检索要显示的项目时出现在管理站点(其他地方),尽管包含坏字符的字段实际上并未呈现。

我甚至不能完全确定从哪里开始调试,而不是尝试手动删除违规字符。我的猜测是这是一个配置问题,因为它是特定于环境的,但我不确定从哪里开始。

编辑: 正如Daniel Roseman指出的那样,错误几乎肯定存在于方法 - 或者更准确地说,它调用的另一种方法中。注意有问题的字符在这里的代码中根本没有引用。我想这个异常是在从db结果中构建对象的方法中引发的 - 如果queryset从未被评估过(例如,如果不是self.enabled),那么就没有错误。下面的代码:

def get_blocking_events(self): 
    return Event.objects.filter(<get a set of events>) 

def get_blocking_reason(self): 
    blockers = self.get_blocking_events() 
    label = u'' 
    if not self.enabled: 
     label = u'Sponsor disabled' 
    elif len(blockers) > 0: 
     label = u'Pending follow-up: "{0}" ({1})'.format(blockers[0],blockers[0].creator.email) 
     if len(blockers) > 1: 
      label += u" and {0} other event".format(len(blockers)-1) 
     if len(blockers) > 2: 
      label += u"s" 
    return label 

def __unicode__(self): 
    label = self.name 
    blocking_msg = self.get_blocking_reason() 
    if len(blocking_msg): 
     label += u" ({0})".format(blocking_msg) 
    return label 

这里的堆栈跟踪的尾部,为了好玩:

File "/opt/opt.LOCAL/Django-1.2.1/django/template/__init__.py", line 954, in render 
    dict = func(*args) 

File "/opt/opt.LOCAL/Django-1.2.1/django/contrib/admin/templatetags/admin_list.py", line 209, in result_list 
    'results': list(results(cl))} 

File "/opt/opt.LOCAL/Django-1.2.1/django/contrib/admin/templatetags/admin_list.py", line 201, in results 
    yield list(items_for_result(cl, res, None)) 

File "/opt/opt.LOCAL/Django-1.2.1/django/contrib/admin/templatetags/admin_list.py", line 138, in items_for_result 
    f, attr, value = lookup_field(field_name, result, cl.model_admin) 

File "/opt/opt.LOCAL/Django-1.2.1/django/contrib/admin/util.py", line 270, in lookup_field 
    value = attr() 

File "/opt/opt.LOCAL/Django-1.2.1/django/db/models/base.py", line 352, in __str__ 
    return force_unicode(self).encode('utf-8') 

File "/opt/opt.LOCAL/Django-1.2.1/django/utils/encoding.py", line 88, in force_unicode 
    raise DjangoUnicodeDecodeError(s, *e.args) 

DjangoUnicodeDecodeError: 'utf8' codec can't decode bytes in position 956-958: invalid data. You passed in <Sponsor: [Bad Unicode data]> (<class 'SJP.alcohol.models.Sponsor'>) 
+0

在这些情况下通常的罪魁祸首是模型的__unicode__方法。你能告诉我们代码吗? – 2010-11-06 18:17:28

+0

数据库中的数据怎么样 - 你的表是使用UTF8还是一些ISO拉丁编码? – 2010-11-06 19:07:30

+0

数据库是MS SQL Server,所以我的理解是没有数据库范围的编码;但是,所讨论的列是nvarchar,这意味着数据被编码为UTF-16。我还会注意到,通过django dev服务器读取具有相同应用程序代码的完全相同的数据库时,我没有任何问题。 – 2010-11-06 20:06:09

回答

1

原来,这可能是由于连接到SQL Server的FreeTDS层。尽管FreeTDS为自动转换编码提供了一些支持,但是我的设置可能配置错误或者工作不正确。

现在我已经移植到MySQL了,而不是打这场战斗。

1

这里的问题是,在的unicode您使用以下行:

label += " ({0})".format(blocking_msg) 

不幸的是,在python 2.x中,它试图将blocking_msg格式化为ascii字符串。你打算输入的内容是:

label += u" ({0})".format(blocking_msg) 
+0

谢谢,但没有运气。可以肯定的是,我将这些函数中的所有字符串文字转换为Unicode字符串。 – 2010-11-06 18:57:25

+0

db中的编码是什么? – 2010-11-06 19:05:12