Django & Suds: UnicodeEncodeError при использовании QuerySets - PullRequest
3 голосов
/ 11 февраля 2012

Как любой разработчик Python, я годами возился с проблемой Unicode в Python. Но сейчас у меня ситуация, которая сводит меня с ума, и я не могу решить ее самостоятельно. Это заняло 1 день, включая повторные встречи.

Моя установка - это небольшое приложение Django, которое подключается к удаленной системе через SOAP (используя Suds), извлекает некоторые данные и ищет их в базе данных Django:

from myapp.models import Customer
client = suds.client.Client(...)
customer = client.service.getCustomerByEmail('foo@bar.com')

type(customer.email): <class 'suds.sax.text.Text'>

customer_exists = Customer.objects.filter(email=customer.email)

Теперь адрес электронной почты клиента имеет немецкий Umlaut ü, который позволяет Django создать исключение следующим образом:

Traceback (most recent call last):
  File "run_anatomy_client.py", line 19, in <module>
    print client.main()
  File "/Users/user/Documents/workspace/Wawi/application/myapp/client.py", line 282, in main
    if not Customer.objects.filter(email=customer.email.encode('latin1')):
  File "/Users/user/Documents/workspace/Wawi/application/myapp/client.py", line 76, in sync_customer
    if not customer_exists:
  File "/Users/user/Documents/workspace/Wawi/pyenv/lib/python2.7/site-packages/django/db/models/query.py", line 113, in __nonzero__
    iter(self).next()
  File "/Users/user/Documents/workspace/Wawi/pyenv/lib/python2.7/site-packages/django/db/models/query.py", line 107, in _result_iter
    self._fill_cache()
  File "/Users/user/Documents/workspace/Wawi/pyenv/lib/python2.7/site-packages/django/db/models/query.py", line 772, in _fill_cache
    self._result_cache.append(self._iter.next())
  File "/Users/user/Documents/workspace/Wawi/pyenv/lib/python2.7/site-packages/django/db/models/query.py", line 273, in iterator
    for row in compiler.results_iter():
  File "/Users/user/Documents/workspace/Wawi/pyenv/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 680, in results_iter
    for rows in self.execute_sql(MULTI):
  File "/Users/user/Documents/workspace/Wawi/pyenv/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 735, in execute_sql
    cursor.execute(sql, params)
  File "/Users/user/Documents/workspace/Wawi/pyenv/lib/python2.7/site-packages/django/db/backends/util.py", line 43, in execute
    logger.debug('(%.3f) %s; args=%s' % (duration, sql, params),
UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc' in position 28: ordinal not in range(128)

Я уже поигрался с encode (), decode (), изменил кодировку исходного файла, а также структуру базы данных, которая в настоящее время выглядит следующим образом:

mysql> show variables like '%character%';
+--------------------------+-----------------------------------------+
| Variable_name            | Value                                   |
+--------------------------+-----------------------------------------+
| character_set_client     | latin1                                  |
| character_set_connection | latin1                                  |
| character_set_database   | utf8                                    |
| character_set_filesystem | binary                                  |
| character_set_results    | latin1                                  |
| character_set_server     | latin1                                  |
| character_set_system     | utf8                                    |
| character_sets_dir       | /opt/local/share/mysql5/mysql/charsets/ |
+--------------------------+-----------------------------------------+
8 rows in set (0.00 sec)

Странно то, что если я установил точку трассировки и выполнил ту же самую строку в оболочке Django, то она прекрасно работает при использовании encode ():

(Pdb) Customer.objects.filter(email=customer.email)
*** UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc' in position 28:     ordinal not in range(128)
(Pdb) Customer.objects.filter(email=customer.email.encode('utf-8'))
[]

Буду благодарен за любые подсказки ..

Ответы [ 2 ]

2 голосов
/ 03 апреля 2013

suds.sax.text.Text наследует от Unicode

class Text(unicode):
    """
    An XML text object used to represent text content.
    @ivar lang: The (optional) language flag.
    @type lang: bool
    @ivar escaped: The (optional) XML special character escaped flag.
    @type escaped: bool
    """

Вы можете просто кодировать в UTF-8, если хотите работать с.

email = customer.email.encode("utf-8")
customer_exists = Customer.objects.filter(email=email)
0 голосов
/ 28 марта 2014

Я потратил более 2 часов, пытаясь выяснить, что происходит и почему я не могу сохранить объекты Django после присвоения значений из структур данных Suds полям объектов.

Как упомянул @guillaumevincent, класс Suds Text наследуется от юникода, и реализация не на 100% правильная, поэтому Django завершается неудачно после попытки выполнить некоторые операции, которые будут работать с базовым типом юникода.

Так что для примера из вопроса я бы сделал

customer_exists = Customer.objects.filter(email=unicode(customer.email))

И в моем случае я сделал это аналогично

django_obj.field_name = suds_obj.field_name

Надеюсь, это сэкономит кому-то время :)

...