はじめに
DjangoでMySQLのJSON型を使いたい時に必要な作業を書きました。
前提条件
- MySQLが既に導入・DB構築されており、mysql.server startで起動されている状態である
- mysqlclientを導入し、MySQLに接続するためのsettings.pyの設定が済んでいる(今回使用するDjango-mysqlはmysqlclientを前提としている)
今回使用したモジュールのバージョン
- Django v2.1.15
- mysqlclient v1.4.6
- Django-mysql v3.3.0
作業手順
- Django-mysqlのインストール
- モデル追加
- settings.pyの編集
1.Django-mysqlのインストール
DjangoでMySQL用のJSONfieldを使えるようにしてくれるモジュール、Django-mysqlをインストールします。
pip install django-mysql
2.モデル追加
自分のモデル定義にJSONfieldを追加。modelの継承元もdjango_mysqlのものにする。
from django_mysql.models import JSONField, Model class ShopItem(Model): name = models.CharField(max_length=200) attrs = JSONField() def __str__(self): return self.name
3.settings.pyの編集
settings.pyのINSTALLED_APPSに以下を追加する。
(ちなみに、自分の環境では何故かこの設定を行わなくてもJSON型のカラムが生成されてしまったが、公式ドキュメントにある通りきちんと指定した方が無用なトラブルを避けられると思う。)
INSTALLED_APPS = ( ... 'django_mysql', )
公式ドキュメントによると以上で作業は完了なのだが、自分の環境では
?: (django_mysql.W003) The character set is not utf8mb4 for database connection 'default'<br> HINT: The default 'utf8' character set does not include support for all Unicode characters. It's strongly recommended you move to use 'utf8mb4'. See: https://django-mysql.readthedocs.io/en/latest/checks.html#django-mysql-w003-utf8mb4
というエラーが出てしまった。これを解決するため、settings.pyのDB接続情報に'OPTIONS'項目を追加し、utf8mb4という文字コードを指定する。
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'USER': 'xxxxx', 'PASSWORD': 'xxxxx', 'HOST': 'localhost', 'OPTIONS': { 'charset': 'utf8mb4', # <--- Use this } } }
utf8mb4とは何なのか
通常のutf-8は1~4バイトで1文字を表しますが、何故かMySQLにおいてutf-8と名付けられているcharsetは1~3バイトまでしか対応していないため、普段あまり使われないような漢字や絵文字が正しく登録されません。
この問題に対応できるMySQLでのcharsetがutf8mb4で、1~4バイトまで対応しているため、基本的にはこちらを使うのが良いようです。
最初、自分の環境では特にデフォルトのcharsetを指定していなかったのですが、その場合はcharsetがutf8mb4になり、今回のエラーに繋がったようです。
デフォルトの文字コードを指定する
やはり文字コードは明示的に指定した方が良いので、MySQLの設定ファイルに設定を追加します。自身の環境のmy.cnfに以下を追記します。引用
[mysqld] ... character-set-server=utf8mb4 [client] default-character-set=utf8mb4
自身の環境のmy.cnfの場所が不明な場合、
mysql --help | grep my.cnf
で調べられます。引用
今回は以上です。