django,mysql儲存emoji表情,utf8mb4
今天在做後臺的時候發現一個錯誤:
Incorrect string value: '\\xF0\\x9F\\x90\\xA8' for column 'signature' at row 1
發現是引數裡面是一個iOS的表情,也就是系統自帶的emoji表情。
後臺用的是django 1.6,資料庫用的是Mysql 5.5.22,快取用的是redis。
上網瞭解了一下emoji表情,原來一般的字元包括中文用utf8的話,mysql是用3個位元組去儲存的,而emoji表情要用4個位元組的utf8,也就是utf8mb4格式。
首先更改mysql的資料編碼,修改mysql的配置檔案: /etc/mysql/my.cnf 新增:
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
然後重啟,mysql,檢視mysql的編碼
SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
+--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | utf8mb4 | | character_set_connection | utf8mb4 | | character_set_database | utf8mb4 | | character_set_filesystem | binary | | character_set_results | utf8mb4 | | character_set_server | utf8mb4 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | | collation_connection | utf8mb4_unicode_ci | | collation_database | utf8mb4_unicode_ci | | collation_server | utf8mb4_unicode_ci | +--------------------------+----------------------------+
OK,mysql改完了,然後建立資料庫:
create database xxx CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
建立資料庫之後是syncdb,這時 MySQLdb模組 需要1.2.4以上版本,關於MySQLdb模組的安裝可以參考這篇文章,最新版是1.2.5
syncdb成功之後,再次嘗試插入,還是報錯。
查看了一下這部分的原始碼,發現django/db/backends/mysql/base.py中的DatabaseWrapper類中有個kwargs的屬性,裡面有個key叫charset,預設值是utf8,後面做資料庫連線的時候,會用django的settings中,database的options去更新這一項。
class DatabaseWrapper(BaseDatabaseWrapper):
def get_connection_params(self):
kwargs = {
'conv': django_conversions,
'charset': 'utf8',
}
那麼我們修改一下django的settings.py,在資料庫的配置中加入options項。
DATABASES = {
'default': {
#'ENGINE': 'sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'ENGINE': 'django.db.backends.mysql',
#'NAME': '/opt/media/session.db', # Or path to database file if using sqlite3.
'NAME': DATABASE_NAME,
'USER': 'root', # Not used with sqlite3.
'PASSWORD': DATABASE_PASSWORD, # Not used with sqlite3.
'HOST': DATABASE_HOST, # Set to empty string for localhost. Not used with sqlite3.
'PORT': DATABASE_PORT, # Set to empty string for default. Not used with sqlite3.
'OPTIONS': {'charset':'utf8mb4'},
},
}
然後再嘗試插入emoji表情,結果正常,取出來結果也正常,ios和android都可以正常使用。
由於實際在阿里雲上部署的時候,mysql使用的是docker container,似乎不方便修改container裡面的mysql配置檔案(進去container,裡面沒有vi),嘗試不改配置檔案,只是在建立資料庫的時候指定character set 為utf8mb4,collate為 utf8mb4_unicode_ci,發現其實也可以用,那麼應該是隻需要保證連線mysql的時候是用utf8mb4,並且mysql資料的編碼格式是utf8mb4即可。