Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » Django
  • » Вернуть страницу с кодировкой отличной от стандартной для проекта [РЕШЕНО] [RSS Feed]

#1 Март 22, 2012 21:36:36

kmike
От:
Зарегистрирован: 2009-12-07
Сообщения: 56
Репутация: +  4  -
Профиль   Отправить e-mail  

Вернуть страницу с кодировкой отличной от стандартной для проекта [РЕШЕНО]

Гляньте сюда: https://bitbucket.org/kmike/django-assist-ru/src/9aa1bdb4cc6e/assist/decorators.py

строчку с “response.content = response.content.replace(UTF8_HEADER, CP1251_HEADER, 1)” можно выкинуть, если Content-Type в шаблоне правильный.

Джанга ожидает юникод везде во “внутренностях” (втч при рендеринге шаблонов), и это замечательно. Кодировка имеет значение при общении с внешним миром - поэтому кодировать лучше все на выходе, как можно позже.

Еще хорошо бы завязать с методом тыка при работе с кодировками - лучше один раз разобраться по-нормальному, там ничего сложного же нет. Советы в духе “попробуйте ‘это_проверка’.encode('cp1251')” - это ужасно.

“open(root_dir+'/templates/test.html').read()” - так тоже не делайте, пожалуйста - опять байтовые строки вместо юникода, не закрываете файл, не используете более простые джанговские средства почему-то.



Офлайн

#2 Март 23, 2012 03:16:50

JOHN_16
От: Россия, Петропавловск-Камчатск
Зарегистрирован: 2010-03-22
Сообщения: 3292
Репутация: +  221  -
Профиль   Отправить e-mail  

Вернуть страницу с кодировкой отличной от стандартной для проекта [РЕШЕНО]

kmike
учше один раз разобраться по-нормальному, там ничего сложного же нет.
я с удовольствием выслушаю ваше универсальное предложение по работе с кодировками (а то я бился, бился и у меня ничего не вышло), создайте тему в разделе флейм и там обсудим с другими участниками форума эту проблему. В противном случае, это всего лишь голословное заявление=)
kmike
не закрываете файл
Вы не правы. Проверьте сами (lsof для Linux или , например, Unlocker для windows)
kmike
не используете более простые джанговские средства почему-то.
Это вы об django.template.loader.get_template() ? Ну там нчиег осверхординарного нет: file.read().decode(settings.FILE_CHARSET), но тем не менее замечание ваше принимаю, так как оно имеет смысл в целом,но не решающее в данном вопросе.



_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Отредактировано (Март 23, 2012 03:30:03)

Офлайн

#3 Март 23, 2012 09:46:21

kmike
От:
Зарегистрирован: 2009-12-07
Сообщения: 56
Репутация: +  4  -
Профиль   Отправить e-mail  

Вернуть страницу с кодировкой отличной от стандартной для проекта [РЕШЕНО]

В смысле, “лучше разобраться по-нормальному” - это голословное утверждение?) Универсальное решение при работе с кодировками одно - это четко понимать, что такое кодировка, что такое байты и что такое юникод :)

Проблемы с кодировками вылезают оттого, что во 2м питоне в объектах класса str хранятся “голые” байты. Когда такие переменные используются для хранения строк текста, то получается, что прямо в самой переменной нет никакой информации о том, в какой кодировке строка (== по какому алгоритму была получена последовательность байт для данного текста). Восстановить текст из последовательности байт можно разными способами (==с разными кодировками), а т.к. у питона никакой информации о кодировке нет, то он выбирает черти какую кодировку (обычно это оказывается ascii) и пробует с ней декодировать текст - иногда это работает, иногда падает. Собственно, главное отличие 3го питона от 2го по части юникода в том, что 3й НЕ пробует декодировать строку с черти какой кодировкой, а просто всегда падает с исключением (а не иногда, как 2й).

Отсюда 2 следствия - вы всегда должны знать, в какой кодировке к вам поступают байтовые строки, и перед операциями с ними как с текстом декодировать их в питоний unicode. unicode - это такой тип, переменные которого гарантированно могут хранить все буквы текста (как это делается внутри - считается, что не наша забота), эдакая абстрацкия “текст”.

Если б не существовало “внешнего мира”, все строки были бы в питоне юникодными и не было бы никаких проблем с кодировками. Но “внешний мир” существует, и поэтому нужно декодировать байты, полученные из внешнего мира (например, из файла) и кодировать unicode в какую-то кодировку (== преобразовывать в последовательность байт по какому-то алгоритму, например, utf8 или cp1251), чтоб внешний мир мог данные принять обратно (например, при записи в файл или отдаче ответа на веб-запрос).

Джанга многое из этого делает автоматически (запрос она декодирует в unicode, ответ кодирует в кодировку), так что “внутри” у нас везде юникод и никаких проблем. В большинстве случаев это работает отлично, но когда часть страниц нужно отдавать в одной кодировке, а часть в другой, то приходится перекодировать ответ “руками” - например, так, как по ссылке в примере.

Если нужно запрос декодировать из другой кодировки, то у request есть свойство encoding, которое можно во вьюхе установить в нужное значение, и тогда GET, POST из запроса будут декодированы в юникод по нужному алгоритму (== как текст в данной кодировке).

Про файл и open(). Я же написал “вы не закрываете файл”, а не “файл не закрывается”.
open(path).read() закрывает файл только из-за особенностей реализации GC в CPython, в pypy и других реализациях файл не закроется - imho лучше приучиться писать все явно: with codecs.open(path, ‘rt’, 'utf8) as f:



Отредактировано (Март 23, 2012 09:49:22)

Офлайн

#4 Март 23, 2012 11:15:44

JOHN_16
От: Россия, Петропавловск-Камчатск
Зарегистрирован: 2010-03-22
Сообщения: 3292
Репутация: +  221  -
Профиль   Отправить e-mail  

Вернуть страницу с кодировкой отличной от стандартной для проекта [РЕШЕНО]

kmike
Вот вы хорошо пишите:)похвально. Только все это я знаю, за исключением особенностей реализации.
Вот как раз проблема и всплывает в том что в реальной жизни далеко не всегда можно заранее знать в какой кодировке придет строка, и реальное приложение остановит свою работу при возникновении в случайном месте UnicodeEncode/Decode exception. Я думал может быть вы в подобной ситуации знаете выход, как видите просто понимание строк и юникода здесь не выход. Я как то писал некую функцию, которую нужно было применять к любой строке которая попадает в программу извне, предназначена она была вернуть корректно сформированный объект юникода. Но что то там все равно не срасталось.

kmike
Про файл и open(). Я же написал “вы не закрываете файл”, а не “файл не закрывается”.
Ну вот тут как бы неоднозначно вас понять можно, лучше было бы перефразировать, я бы вас сразу понял как надо.

декоратор по ссылочке сверху опробую несколько позже



_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Офлайн

#5 Март 23, 2012 11:32:49

kmike
От:
Зарегистрирован: 2009-12-07
Сообщения: 56
Репутация: +  4  -
Профиль   Отправить e-mail  

Вернуть страницу с кодировкой отличной от стандартной для проекта [РЕШЕНО]

Чтоб UnicodeEncode/Decode exception возникал не в случайном месте, а в строго определенном, нужно декодировать строку в юникод как можно раньше, и кодировать в кодировку как можно позже, а с байтовыми строками не работать вовсе, вот я о чем)

Если неизвестно, в какой кодировке текст приходит извне (или какую кодировку внешний мир хочет), то тут нужно не питоний код писать, а выяснять, в какой кодировке он приходит (или какую кодировку хочет).

По конкретной проблеме - вы же правильно уже все сделали - установили, что ftp-сервер хочет cp1251, и придумали, как заставить браузер передать 1251 - вывести ссылку на странице с 1251; осталось страничку в 1251 вернуть. Про “лучше 1 раз разобраться” я не вам писал, а автору ‘это_проверка’.encode('cp1251')

Кстати, вот так еще можно вроде:

response = HttpResponse(rendered_template.encode('cp1251'))
response._charset = ‘cp1251’
return response



Офлайн

#6 Март 25, 2012 22:50:46

JOHN_16
От: Россия, Петропавловск-Камчатск
Зарегистрирован: 2010-03-22
Сообщения: 3292
Репутация: +  221  -
Профиль   Отправить e-mail  

Вернуть страницу с кодировкой отличной от стандартной для проекта [РЕШЕНО]

kmike
Спасибо, проблема решена. решение оформлено в первом посте.



_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Офлайн

  • Начало
  • » Django
  • » Вернуть страницу с кодировкой отличной от стандартной для проекта [РЕШЕНО][RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version