Saya mendapat pesan kesalahan aneh ketika mencoba menyimpan first_name, last_name ke model auth_user Django.
Contoh gagal
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
Contoh sukses
user.first_name = u'Marcin'
user.last_name = u'Król'
user.save()
>>> SUCCEED
Pengaturan 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)
Tabel charset dan collation
Tabel auth_user memiliki charset utf-8 dengan collation utf8_general_ci.
Hasil dari perintah UPDATE
Itu tidak menimbulkan kesalahan ketika memperbarui nilai-nilai di atas ke tabel auth_user dengan menggunakan perintah UPDATE.
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
Nilai-nilai gagal yang tercantum di atas dapat diperbarui ke tabel PostgreSQL ketika saya mengganti database backend di Django. Ini aneh.
mysql> SHOW CHARACTER SET;
+----------+-----------------------------+---------------------+--------+
| Charset | Description | Default collation | Maxlen |
+----------+-----------------------------+---------------------+--------+
...
| utf8 | UTF-8 Unicode | utf8_general_ci | 3 |
...
Tetapi dari http://www.postgresql.org/docs/8.1/interactive/multibyte.html , saya menemukan yang berikut:
Name Bytes/Char
UTF8 1-4
Apakah ini berarti unicode char memiliki maksimal 4 byte di PostgreSQL tetapi 3 byte di MySQL yang menyebabkan kesalahan di atas?
Jawaban:
Tak satu pun dari jawaban ini memecahkan masalah bagi saya. Penyebab utamanya adalah:
Anda tidak dapat menyimpan karakter 4-byte di MySQL dengan set karakter utf-8.
MySQL memiliki batas 3 byte pada utf-8 karakter (ya, itu aneh, disimpulkan dengan baik oleh pengembang Django di sini )
Untuk mengatasi ini, Anda perlu:
settings.py
Catatan: Saat membuat ulang basis data Anda, Anda mungkin mengalami masalah ' Kunci spesifik terlalu panjang '.
Penyebab paling mungkin adalah
CharField
yang memiliki max_length 255 dan beberapa jenis indeks di atasnya (misalnya unik). Karena utf8mb4 menggunakan 33% lebih banyak ruang daripada utf-8 Anda harus membuat bidang ini 33% lebih kecil.Dalam hal ini, ubah max_length dari 255 menjadi 191.
Atau Anda dapat mengedit konfigurasi MySQL Anda untuk menghapus pembatasan ini tetapi tidak tanpa beberapa hackery Django
UPDATE: Saya baru saja mengalami masalah ini lagi dan akhirnya beralih ke PostgreSQL karena saya tidak dapat mengurangi saya
VARCHAR
menjadi 191 karakter.sumber
'charset': 'utf8mb4'
opsi dalam pengaturan Django sangat penting, seperti yang dikatakan @Xerion. Akhirnya, masalah indeks berantakan. Hapus indeks pada kolom, atau buat panjangnya tidak lebih dari 191, atau gunakan aTextField
!Saya memiliki masalah yang sama dan mengatasinya dengan mengubah set karakter kolom. Meskipun database Anda memiliki set karakter default,
utf-8
saya pikir itu mungkin untuk kolom database memiliki set karakter yang berbeda di MySQL. Inilah SQL QUERY yang saya gunakan:sumber
Jika Anda memiliki masalah ini, inilah skrip python untuk mengubah semua kolom basis data mysql Anda secara otomatis.
sumber
db.commit()
sebelumnyadb.close()
.Jika ini adalah proyek baru, saya hanya akan membuang database, dan membuat yang baru dengan charset yang tepat:
sumber
- --character-set-server=utf8
Saya baru saja menemukan satu metode untuk menghindari kesalahan di atas.
Simpan ke basis data
Apakah ini satu-satunya metode untuk menyimpan string seperti itu ke dalam tabel MySQL dan mendekodekannya sebelum dirender ke templat untuk ditampilkan?
sumber
.encode('unicode_escape')
sebenarnya tidak menyimpan karakter unicode dalam database. Anda memaksa semua klien untuk membuka kode sebelum menggunakannya, yang berarti itu tidak akan berfungsi dengan baik dengan django.admin atau segala hal lainnya.utf8
set karakter 3-byte MySQL 5.1 .utf8mb4
yang memungkinkan lebih dari Basic Multilingual Plane untuk disimpan. Saya tahu, Anda akan berpikir "UTF8" adalah semua yang diperlukan untuk menyimpan Unicode sepenuhnya. Nah, whaddaya tahu, bukan. Lihat dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.htmlAnda dapat mengubah susunan bidang teks Anda menjadi UTF8_general_ci dan masalah akan terpecahkan.
Perhatikan, ini tidak dapat dilakukan di Django.
sumber
Anda tidak mencoba menyimpan string unicode, Anda mencoba menyimpan bytestrings dalam pengkodean UTF-8. Jadikan mereka literal string unicode yang sebenarnya:
atau (ketika Anda tidak memiliki string literal) mendekode mereka menggunakan pengkodean utf-8:
sumber
Cukup ubah meja Anda, tidak perlu apa-apa. jalankan saja query ini pada basis data. ALTER TABLE
table_name
CONVERT KE SET KARAKTER utf8itu pasti akan berhasil.
sumber
Peningkatan jawaban @madprops - solusi sebagai perintah manajemen Django:
Semoga ini bisa membantu siapa pun kecuali saya :)
sumber