Является ли Django двойным кодированием строки Unicode (utf-8?)? - PullRequest
6 голосов
/ 04 июня 2010

У меня проблемы с сохранением и выводом символа ndash как UTF-8 в Django.

Я получаю данные из API. В необработанном виде, как получено и просмотрено в текстовом редакторе, данная единица данных может быть похожа на:

"I love this detergent \u2013 it is so inspiring." 

(\ u2013 - это html-объект).

Если я получу это прямо из API и выведу его на Django, нет проблем. Это отображается в моем браузере как длинная черта. Я заметил, что мне нужно сделать decode('utf-8'), чтобы избежать ошибки «кодек ascii не может закодировать символ», хотя я пытаюсь выполнить некоторые операции с этим текстом в моем представлении. Согласно шаблону Django Debug Toolbar, текст идет к шаблону как «Мне нравится это моющее средство. Это так вдохновляет».

При сохранении в MySQL и чтении для вывода через тот же вид и шаблон, в конечном итоге он выглядит как

"I love this detergent – it is so inspiring"

Моя таблица MySQL установлена ​​на DEFAULT CHARSET=utf8.

Теперь, когда я читаю данные из базы данных через монитор MysQl в терминале, настроенном на Utf-8, он отображается как

"I love this detergent – it is so inspiring" 

(правильно - показывает ndash)

Когда я использую mysqldb в оболочке python, эта строка будет

"I love this detergent \xe2\x80\x93 it is so inspiring" 

(это правильный UTF-8 для ndash)

Однако , если я запускаю python manage.py shell, а затем

In [1]: import myproject.myapp.models ThatTable
In [2]: msg=ThatTable.objects.all().filter(thefield__contains='detergent')
In [3]: msg
Out[4]: [{'thefield': 'I love this detergent \xc3\xa2\xe2\x82\xac\xe2\x80\x9c it is so inspiring'}]

Мне кажется, что Django взял \xe2\x80\x93 для обозначения трех отдельных символов и закодировал его как UTF-8 в \xc3\xa2\xe2\x82\xac\xe2\x80\x9c. Это отображается как «потому что \ xe2, по-видимому,», \ x80, по-видимому, € и т. Д. Я проверил, и это равно , как и его отправка в шаблон.

Если вы декодируете длинную последовательность в Python, однако, с помощью decode('utf-8'), результат будет \xe2\u20ac\u201c, который также отображается в браузере как ... Попытка декодировать его снова приводит к UnicodeDecodeError.

Насколько я знаю, я следовал советам Django для Unicode (настроил MySQL).

Любые предложения о том, что я, возможно, неправильно настроил?

addendum Кажется, эта проблема возникла и в других областях или системах. Например, при поиске \ xc3 \ xa2 \ xe2 \ x82 \ xac \ xe2 \ x80 \ x9c я обнаружил в http://pastie.org/908443.txt скрипт для «исправления плохих сущностей UTF8.», также найденный в плагине импорта WordPress RSS. Он просто заменяет эту последовательность на & ndash ;. Я хотел бы решить это правильно, хотя!

О, и я использую Django 1.2 и Python 2.6.5.

Я могу подключиться к той же базе данных с помощью PHP / PDO и распечатать эти данные, не делая ничего особенного, и все выглядит хорошо.

Ответы [ 2 ]

1 голос
/ 04 июня 2010

Это похоже на случай двойного кодирования; У меня нет большого опыта работы с Python, но попробуйте настроить параметры подключения MySQL в соответствии с рекомендациями http://tahpot.blogspot.com/2005/06/mysql-and-python-and-unicode.html

Что я предполагаю, так это то, что соединение имеет значение latin1, поэтому MySQL снова пытается закодировать строку перед сохранением в поле UTF-8 Код там, в частности, этот бит:

РЕДАКТИРОВАТЬ: с Python при создании подключение к базе данных добавить следующее flag: init_command = 'SET NAMES utf8'.

Дополнительно установите следующее в MySQL my.cnf: набор символов по умолчанию = utf8

это, вероятно, то, что вы хотите.

0 голосов
/ 04 июня 2010

Я добавил set names utf8 к моей последовательности вставки данных php, и теперь в оболочке Python опасающийся ndash отображается как \ x96. Это правильно отображается при чтении и выводе через Django.

Одной из необычных ситуаций в этом отношении является то, что я вставляю данные через PHP. Django выдает set names utf8 автоматически, поэтому, если бы я вставлял и читал данные через Django, эта проблема не возникла бы. PHP использовал значение по умолчанию latin1, я полагаю

Как интересное замечание: если раньше я мог читать данные из PHP, и они нормально отображались в браузере, то теперь ndash - это , если я не вызову set names перед чтением данных.

Итак, теперь это работает, и я надеюсь, что мне никогда не придется понимать, что происходило раньше!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...