2010-11-06 76 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