Кодировка символов Django - PullRequest
1 голос
/ 06 ноября 2010

Я работаю над новым сайтом Django и после миграции в кучу данных начал сталкиваться с глубоко разочаровывающим DjangoUnicodeDecodeError. Плохой персонаж - \ xe8 (электронная могила).

Есть две проблемы:

Это происходит только на производственном сервере, на котором запущен процесс fcgi с выходом из Apache (при запуске того же кода с той же базой данных на сервере разработчиков Django проблем нет)

Рассматриваемая трассировка стека полностью находится в коде Django. Это происходит на сайте администратора (и в других местах) при получении элемента для отображения, хотя поле, содержащее плохой символ, фактически не отображается.

Я даже не совсем уверен, с чего начать отладку, если не считать попытки удалить оскорбительные символы вручную. Я предполагаю, что это проблема конфигурации, поскольку она зависит от конкретной среды, но я также не уверен, с чего начать.

EDIT: Как отметил Дэниэл Роузман, ошибка почти наверняка заключается в методе unicode - или, точнее, другом методе, который он вызывает. Обратите внимание, что оскорбительные символы находятся в поле, на которое здесь вообще нет ссылок в коде. Я полагаю, что исключение возникает в методе, который создает объект из результата db - если набор запросов никогда не оценивается (например, если не 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'>)

Ответы [ 2 ]

1 голос
/ 10 ноября 2010

Оказывается, это, вероятно, из-за уровня FreeTDS, который подключается к SQL Server. Хотя FreeTDS предоставляет некоторую поддержку для автоматического преобразования кодировок, моя установка либо неправильно настроена, либо не работает должным образом.

Вместо того, чтобы сражаться в этой битве, я сейчас перешел на MySQL.

1 голос
/ 06 ноября 2010

Проблема здесь в том, что в Юникод вы используете следующую строку:

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

И, к сожалению, в python 2.x он пытается отформатировать blocking_msg как строку ascii. То, что вы хотели напечатать, было:

label += u" ({0})".format(blocking_msg)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...