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即可。

網上有更完整的關於存儲emoji表情到mysql的例子可以參考:http://blog.manbolo.com/2014/03/31/using-emojis-in-django-model-fields
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章