UnicodeDecodeError: кодек 'ascii' не может декодировать байт 0xc4 в позиции 1: порядковый номер не входит в диапазон(128)
Итак, как следует из названия вопроса, у меня проблема с кодированием/декодированием строк.
Я использую: python 2.7 | django 1.11 | jinja2 2.8
В принципе, я получаю некоторые данные из базы данных, сериализую их, устанавливаю на них кэш, затем получаю кэш, десериализую его и вывожу в шаблон.
< < <active_agents = User.region_objects.get_active_agents()
agents_by_commission_last_month = active_agents.values(....
"first_name", "last_name").order_by(
'-total_paid_transaction_value_last_month')
Пример сериализованного словаря выглядит так (у меня их 10):
Затем, когда я устанавливаю кэш, я делаю это следующим образом:
for key, value in context.items():
......
value = json.dumps(list(value), default=str, ensure_ascii=False).encode('utf-8')
, где value - список словарей, возвращаемый .values()
из вышеупомянутого кода, а key - region_agents_by_commission_last_month
(как переменная из предыдущего кода)
Теперь мне нужно получить кэш. Поэтому я выполняю тот же процесс, но в обратном направлении.
serialized_keys = ['agencies_by_commission_last_month',
'region_agents_by_commission_last_month', 'region_agents_by_commission_last_12_months',
'region_agents_by_commission_last_30_days',
'agencies_by_commission_last_year',
'agencies_by_commission_last_12_months',
'agencies_by_commission_last_30_days',
'region_agents_by_commission_last_year',
'agency',
'for_agent']
context = {}
for key, value in region_ranking_cache.items():
if key in serialized_keys:
objects = json.loads(value, object_hook=_decode_dict)
for serilized_dict in objects:
....
d['full_name'] = d['first_name'] + " " + d['last_name']
full_name = d['full_name'].decode('utf-8').encode('utf-8')
d['full_name'] = full_name
print(d['full_name'])
....
где _decode_dict для object_hook выглядит следующим образом:
Результат печати: Cătălin Pintea , что нормально.
Но в словаре я отображаю: 'full_name': 'C\xc4\x83t\xc4\x83lin Pintea',
def _decode_list(data):
rv = []
for item in data:
if isinstance(item, unicode):
item = item.encode('utf-8')
elif isinstance(item, list):
item = _decode_list(item)
elif isinstance(item, dict):
item = _decode_dict(item)
rv.append(item)
return rv
def _decode_dict(data):
rv = {}
for key, value in data.items():
if isinstance(key, unicode):
key = key.encode('utf-8')
if isinstance(value, unicode):
value = value.encode('utf-8')
elif isinstance(value, list):
value = _decode_list(value)
elif isinstance(value, dict):
value = _decode_dict(value)
rv[key] = value
return rv
В основном, я использую эту функцию object hook для того, чтобы кодировать() в utf-8 все ключи и значения, когда json.loads
.
Вот как я избежал появления этой ошибки в views.py
.
Ошибка
Где-то в шаблоне я использую:
<td>{{ agent.full_name }}</td>
А agent.full_name берется из : 'full_name': 'C\xc4\x83t\xc4\x83lin Pintea',
И именно отсюда возникает ошибка. Я пробовал другие вещи, но я предполагаю, что это ограничение python 2.7. Обычно я использую python 3.9, но для этого проекта мне приходится использовать 2.7. Я пробовал другие ответы здесь, но ничего действительно не помогло.
Может ли кто-нибудь помочь мне правильно сериализовать этот словарь и как я могу избежать этого беспорядка?
Надеюсь, я ясно выразился.
Всем хорошего дня!
Итак, мне удалось решить свою проблему.
- Я понял, что
active_agents.values(...."first_name", "last_name").order_by('-total_paid_transaction_value_last_month')
извлекал словарь, в котором ключ и значения уже были в юникоде (из-за того, как он был настроен в models.py, django 1.11 и python2.7. Таким образом, процесс сериализации прошел нормально. Действительно, конечный результат, который отправлялся в шаблон, выглядел как’C\xc4\x83t\xc4\x83lin'
. Ошибка возникла из-за /xc4/. .
- Для того чтобы исправить ее в шаблоне, я сделал следующее:
{{ agent.full_name.decode("utf-8") }}, что дало мне правильный результат:
Cătălin Pintea
Спасибо @BoarGules. Это правда, что d['last_name']
и d['first_name']
были в юникоде. Поэтому, когда я выполнял конкатенацию, мне пришлось добавить u" "
.