1

Тема: Кирилиця та bottle

Доброго вечора панове!

Вирішив трішки заюзати bottle, та зіткнувся з вічною проблемою кодування :)

Наприклад маємо такий код:

# -*- coding: UTF-8 -*-
from bottle import request, run, route


@route('/') 
def main():
    return '<form method="POST"><input type="text" name="name" value="Текст"/><input type="submit"/></form>'


@route('/', method='POST')
def main_post():
    return '<pre><b>Значення:</b> ' + request.POST['name'] + '</pre>'

run(port=80)

Рез-тат:
http://i63.fastpic.ru/big/2014/1107/45/a984b90fbba8c70c0c818290d1e8ad45.png

І контент-тайп ставив по-різному і декоде, а ніфіга.
При виконанні..

request.body.readlines()

.. маю на виході

name=%D0%A2%D0%B5%D0%BA%D1%81%D1%82

Тобто бачимо, що слово "Текст" кодується по UTF8, але чомусь нічого не допомагає..

Хто зтикався з подібною проблемою? Як його вирішити?

2 Востаннє редагувалося Kane (07.11.2014 20:29:10)

Re: Кирилиця та bottle

Запрацювало.. Oo

...
return '<pre><b>Значення:</b> ' + request.POST['name'].encode('latin1').decode('utf8') + '</pre>'
...

upd:

Because WSGI 3333 (the Python3 WSGI standard) requires all incoming data to be latin1-encoded unicode and a framework has no way to guess the correct encoding.

Bottle assumes utf-8 in many places already, though. This should be cleaned up in a future release (it breaks backward compatibility, so it's not that easy)

Подякували: 0xDADA11C7, Singularity2

3 Востаннє редагувалося P.Y. (07.11.2014 21:46:17)

Re: Кирилиця та bottle

Ніколи не мав справи з bottle, але, припускаю, шукати треба десь у цьому напрямку:

class FormsDict(*a, **k)
This MultiDict subclass is used to store request form data. Additionally to the normal dict-like item access
methods (which return unmodified data as native strings), this container also supports attribute-like access to
its values. Attributes are automatically de- or recoded to match input_encoding (default: ‘utf8’). Missing
attributes default to an empty string.
input_encoding = ‘utf8’
Encoding used for attribute values.
recode_unicode = True
If true (default), unicode strings are first encoded with latin1 and then decoded to match
input_encoding.
decode(encoding=None)
Returns a copy with all keys and values de- or recoded to match input_encoding. Some libraries (e.g.
WTForms) want a unicode dictionary.
getunicode(name, default=None, encoding=None)
Return the value as a unicode string, or the default.

POST, наскільки я можу зрозуміти, є екземпляром цього класу. А те, що відбулося, виглядає як розкодування параметрів форми з latin1. Можливо, треба в main_post() попередньо зробити

request.POST.recode_unicode=False

чи замінити на

    return '<pre><b>Значення:</b> ' + request.POST.decode('utf-8')['name'] + '</pre>'

чи зробити ще якусь магію з POST. Експериментуйте.

З власного досвіду, подібна проблема виникає в більшості веб-API, де використовується юнікодівський внутрішній формат рядка (а не рядки байтів) — західне кодування вважається дефолтовим для веб, і дані форм розкодовуються з нього, або ж сторінка кодується в нього...

P.S. Схоже, моє повідомлення не містить правильного рішення :)

Подякували: Kane1

4

Re: Кирилиця та bottle

Дякую за увагу до теми!

P.Y. написав:

чи замінити на

    return '<pre><b>Значення:</b> ' + request.POST.decode('utf-8')['name'] + '</pre>'

- так, іще один доречний варіант (я його не в тому місці був приліпив, і гадав, чого ж воно не працювало xD).

Гадаю, проблему остаточно вирішено. Як завжди, потрібно лишень напрягтись, і прочитати доку..