Djangoエラー「1366, Incorrect string value」の原因と対処法

Djangoエラー「1366, Incorrect string value」の原因と対処法

DjangoでMySQL接続時に「1366, Incorrect string value」が発生した場合の原因と対処法を解説します。文字コード不一致、utf8mb4設定、database.ymlではなくsettings.pyの確認、DB・テーブル・カラムの文字コード変更手順まで紹介します。

環境

  • OS CentOS Linux release 7.9.2009 (Core)
  • mysql 5.7.32

エラー全文

migrate実行時に発生。

python manage.py migrate

エラー全文

django.db.utils.OperationalError: (1366, "Incorrect string value: '\\xE3\\x82\\xB0\\xE3\\x83\\xAB...' for column 'name' at row 4")

原因

文字コードはDB側もDjango側も「utf8mb4」に設定されていたが、作成済みのDBが別の文字コードになっていたため

mysql

show variables like "chara%";

+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8mb4                    |
| character_set_connection | utf8mb4                    |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | utf8mb4                    |
| character_set_server     | utf8mb4                    |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+

/etc/my.cnf

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
character_set_server=utf8mb4
skip-character-set-client-handshake

settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'hoge',
        'USER': 'root',
        'HOST': 'localhost',
        'PASSWORD': '',
        'PORT': '3306',
        'OPTIONS': {
            'charset': 'utf8mb4'
        }
    }
}

対処法

DBの文字コードを「utf8mb4」変更する

alter database hoge CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

tableの文字コードを変更する場合は、以下となります。

alter table <table-name> CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

補足

1366, "Incorrect string value" は、DjangoからMySQLへ日本語や絵文字などを保存しようとした際に、文字コードの設定が合っていない場合に発生することがあります。

特に、データベースやテーブル、カラムの文字コードが utf8mb4 ではなく latin1 や古い utf8 になっている場合は注意が必要です。

SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

Django側では、settings.pyDATABASES 設定に文字コードを指定しておくと安心です。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'sample_db',
        'USER': 'user',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '3306',
        'OPTIONS': {
            'charset': 'utf8mb4',
        },
    }
}

既存のテーブルに対しては、必要に応じて文字コードを変更します。

ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

日本語や絵文字を扱う可能性がある場合は、データベース作成時点で utf8mb4 を指定しておくことをおすすめします。

参考リンク