Проблемы кодирования Django с MySQL - PullRequest
1 голос
/ 14 мая 2010

Хорошо, у меня настроена база данных MySQL. Большинство таблиц латинские1, а Django отлично с ними справляется. Но некоторые из них - UTF-8, и Django не обрабатывает их.

Вот пример таблицы (все эти таблицы из django-geonames):

DROP TABLE IF EXISTS `geoname`;
SET @saved_cs_client     = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `geoname` (
  `id` int(11) NOT NULL,
  `name` varchar(200) NOT NULL,
  `ascii_name` varchar(200) NOT NULL,
  `latitude` decimal(20,17) NOT NULL,
  `longitude` decimal(20,17) NOT NULL,
  `point` point default NULL,
  `fclass` varchar(1) NOT NULL,
  `fcode` varchar(7) NOT NULL,
  `country_id` varchar(2) NOT NULL,
  `cc2` varchar(60) NOT NULL,
  `admin1_id` int(11) default NULL,
  `admin2_id` int(11) default NULL,
  `admin3_id` int(11) default NULL,
  `admin4_id` int(11) default NULL,
  `population` int(11) NOT NULL,
  `elevation` int(11) NOT NULL,
  `gtopo30` int(11) NOT NULL,
  `timezone_id` int(11) default NULL,
  `moddate` date NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `country_id_refs_iso_alpha2_e2614807` (`country_id`),
  KEY `admin1_id_refs_id_a28cd057` (`admin1_id`),
  KEY `admin2_id_refs_id_4f9a0f7e` (`admin2_id`),
  KEY `admin3_id_refs_id_f8a5e181` (`admin3_id`),
  KEY `admin4_id_refs_id_9cc00ec8` (`admin4_id`),
  KEY `fcode_refs_code_977fe2ec` (`fcode`),
  KEY `timezone_id_refs_id_5b46c585` (`timezone_id`),
  KEY `geoname_52094d6e` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
SET character_set_client = @saved_cs_client;

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

>>> import MySQLdb
>>> from django.conf import settings
>>> 
>>> conn = MySQLdb.connect (host = "localhost",
... user = settings.DATABASES['default']['USER'],
... passwd = settings.DATABASES['default']['PASSWORD'],
... db = settings.DATABASES['default']['NAME'])
>>> cursor = conn.cursor ()
>>> cursor.execute("select name from geoname where name like 'Uni%Hidalgo'");
1L
>>> g = cursor.fetchone()
>>> g[0]
'Uni\xc3\xb3n Hidalgo'
>>> print g[0]
Unión Hidalgo

Однако, если я попытаюсь использовать модель Geoname (которая на самом деле django.contrib.gis.db.models.Model), произойдет сбой:

>>> from geonames.models import Geoname
>>> g = Geoname.objects.get(name__istartswith='Uni',name__icontains='Hidalgo')
>>> g.name
u'Uni\xc3\xb3n Hidalgo'
>>> print g.name
Unión Hidalgo

Здесь довольно ясно ошибка кодирования. В обоих случаях база данных возвращает 'Uni \ xc3 \ xb3n Идальго', но Django (неправильно?) Переводит '\ xc3 \ xb3n' в ³.

Что я могу сделать, чтобы это исправить?

Обновление

Хорошо, это странно:

>>> c = unicode('Uni\xc3\xb3n Hidalgo','utf-8')
>>> c
u'Uni\xf3n Hidalgo'
>>> print c
Unión Hidalgo

Если я заставляю python кодировать строку в Unicode из utf-8, это работает. Однако это воссоздает ошибку:

>>> c = unicode('Unión Hidalgo','latin1')
>>> c
u'Uni\xc3\xb3n Hidalgo'
>>> print c
Unión Hidalgo

Итак, я предполагаю, что MySQL отправляет utf-8, но сообщает Python, что это latin1?

Ответы [ 3 ]

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

Похоже, проблема была в MySQL в конце концов. Я удалил таблицы, воссоздал их с набором символов и сопоставлений в UTF и повторно импортировал все данные.

Сейчас работает.

0 голосов
/ 11 сентября 2017

Джанго 1.10, MariaDB 5.5.47


При создании базы данных очень важно установить набор символов базы данных:

CREATE DATABASE `my_database` CHARACTER SET utf8;

Затем вы можете проверить файлы конфигурации вашего mysql /etc/my.cnf (я использую MariaDB):

[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mariadb according to the
# instructions in http://fedoraproject.org/wiki/Systemd
collation-server=utf8_unicode_ci
init-connect='SET NAMES utf8'
character-set-server=utf8

Также не забудьте перезапустить sqlservice:

sudo systemctl restart mariadb.service

ref:

https://docs.djangoproject.com/en/1.10/ref/databases/#creating-your-database https://mariadb.com/kb/en/the-mariadb-library/setting-character-sets-and-collations/

0 голосов
/ 14 мая 2010

вы можете использовать как это

>>> print g.name.encode('latin1')
Unión Hidalgo
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...