[python] MySQL에서 "잘못된 문자열 값"오류가 장고에서 유니 코드 문자열을 저장할 때



2 Answers

이 답변들 중 어느 것도 나를 위해 문제를 해결하지 못했습니다. 근본 원인은 다음과 같습니다.

utf-8 문자 세트로 MySQL에 4 바이트 문자를 저장할 수 없습니다.

MySQL은 utf-8 문자에 3 바이트 제한을 가지고 있습니다 (예, 그것은 당황하고, 여기 장고 개발자가 멋지게 요약했습니다 )

이 문제를 해결하려면 다음을 수행해야합니다.

  1. utf8mb4 문자 집합 을 사용하도록 MySQL 데이터베이스, 테이블 및 열 변경 (MySQL 5.5 이상에서만 사용 가능)
  2. 다음과 같이 장고 설정 파일에서 문자 세트를 지정하십시오.

settings.py

DATABASES = {
    'default': {
        'ENGINE':'django.db.backends.mysql',
        ...
        'OPTIONS': {'charset': 'utf8mb4'},
    }
}

참고 : 데이터베이스를 다시 만들 때 ' 지정된 키가 너무 깁니다 '라는 문제 발생할 수 있습니다.

가장 큰 원인은 CharField 이며 max_length가 255이고 일종의 인덱스가 있습니다 (예 : 고유). utf8mb4는 utf-8보다 33 % 더 많은 공간을 사용하기 때문에이 필드를 33 % 더 작게 만들 필요가 있습니다.

이 경우 max_length를 255에서 191로 변경하십시오.

또는 MySQL 구성을 편집하여이 제한 사항을 제거 할 수 있지만 일부 장고 해커가 없으면 수정할 수 없습니다.

업데이트 : 나는이 문제를 다시 만났고 내 VARCHAR 를 191 자로 줄일 수 없어 PostgreSQL으로 전환되었습니다 .

Question

Django의 auth_user 모델에 first_name, last_name을 저장하려고하면 이상한 오류 메시지가 나타납니다.

실패한 예

user = User.object.create_user(username, email, password)
user.first_name = u'Rytis'
user.last_name = u'Slatkevičius'
user.save()
>>> Incorrect string value: '\xC4\x8Dius' for column 'last_name' at row 104

user.first_name = u'Валерий'
user.last_name = u'Богданов'
user.save()
>>> Incorrect string value: '\xD0\x92\xD0\xB0\xD0\xBB...' for column 'first_name' at row 104

user.first_name = u'Krzysztof'
user.last_name = u'Szukiełojć'
user.save()
>>> Incorrect string value: '\xC5\x82oj\xC4\x87' for column 'last_name' at row 104

성공 사례

user.first_name = u'Marcin'
user.last_name = u'Król'
user.save()
>>> SUCCEED

MySQL 설정

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

테이블 문자 세트 및 데이터 정렬

테이블 auth_user에는 utf8_general_ci 데이터 정렬을 사용하는 utf-8 charset이 있습니다.

UPDATE 명령의 결과

UPDATE 명령을 사용하여 위의 값을 auth_user 테이블로 업데이트 할 때 오류가 발생하지 않았습니다.

mysql> update auth_user set last_name='Slatkevičiusa' where id=1;
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select last_name from auth_user where id=100;
+---------------+
| last_name     |
+---------------+
| Slatkevi?iusa | 
+---------------+
1 row in set (0.00 sec)

PostgreSQL

Django에서 데이터베이스 백엔드를 전환 할 때 위에 나열된 실패한 값을 PostgreSQL 테이블로 업데이트 할 수 있습니다. 이상합니다.

mysql> SHOW CHARACTER SET;
+----------+-----------------------------+---------------------+--------+
| Charset  | Description                 | Default collation   | Maxlen |
+----------+-----------------------------+---------------------+--------+
...
| utf8     | UTF-8 Unicode               | utf8_general_ci     |      3 | 
...

그러나 http://www.postgresql.org/docs/8.1/interactive/multibyte.html 에서 다음과 같은 것을 발견했습니다.

Name Bytes/Char
UTF8 1-4

그것은 unicode char가 PostgreSQL에서는 4 바이트의 maxlen을 가지고 있지만 위의 오류를 일으킨 MySQL에서는 3 바이트를 의미합니까?




새로운 프로젝트 인 경우 데이터베이스를 삭제하고 적절한 charset을 사용하여 새 데이터베이스를 만듭니다.

CREATE DATABASE <dbname> CHARACTER SET utf8;



텍스트 필드의 정렬을 UTF8_general_ci로 변경할 수 있으며 문제가 해결됩니다.

공지 사항, 장고에서는이 작업을 수행 할 수 없습니다.






Related