【Pyhon・Django】JsonFieldでデータベース上に日本語の文字を登録したい

【Pyhon・Django】JsonFieldでデータベース上に日本語の文字を登録したい


# django # json # python

環境

・Django 1.10 ・Python 3.4

やりたいこと

DjangoというかPostgreSQLでは、JSON Fieldという、Jsonを格納できる型が用意されています。 (なお、Djangoでは1.9以降で対応されているようです。) 単なる文字列ではなく、構造化したデータを持つことが出来るのでユーザー登録情報などある程度情報に柔軟性をもたせたい場合にしようする項目です。

しかし、日本語ユーザーにとっては若干面倒な問題があります(Django1.1系だけかもですが…)。 それは、通常の文字列型などで登録した時は、普通に日本語のまま登録されるのですが、JSON Filedに日本語などの非Ascii文字を登録した場合はエンコードされてしまい、データベース上には以下のような形で文字列が残ってしまいます。

\u4ECA\u65E5\u3082\u5BD2\u3044

まあ、実際にDjangoのORMを介してデータを取得した際は、きちんと日本語で取ってきてくれるので、基本的には大きな問題はないのですが、Django以外のシステム絡んで来るデータだとちょっと話は変わってきますよね。 (後はそもそも、そんなばらばらのデータを格納しておきたくない 笑)

原因

Django内でDictなりをJSON形式に変更する際に、非ASCII文字列はエスケープするような設定がされていることが問題でした。

対応方法

Django 1.09~1.1x系

だいぶ詰まってしまいましたが、以下で解決可能です。 1.JSONFieldを継承して、オリジナルのフィールドを作成する。 2.変換処理を司っている「get_prep_value」の中身を変更する (ensure_ascii=False を指定することでエスケープが行われなくなります。)

import json
from django.contrib.postgres.fields import JSONField


class UnicodeJSONField(JSONField):
    def get_prep_value(self, value):
        if value is not None:
            return json.dump(value, ensure_ascii=False)
        return value

class Model(models.model):
    my_field = UnicodeJSONField

このあたりは公式ページにもきちんと記載がありました。 https://docs.djangoproject.com/en/2.1/howto/custom-model-fields/

Django2.xx系

実際には試していないのですが、以下公式ページの記載を見る限りだと、

https://docs.djangoproject.com/ja/2.1/ref/contrib/postgres/fields/#django.contrib.postgres.fields.JSONField

import json
from django.contrib.postgres.fields import JSONField
from django.core.serializers.json.Django import JSONEncoder

class Model(models.model):
    my_field = UnicodeJSONField(encoder=JSONEncoder(ensure_ascii=False))

こんな感じで行けるのではないでしょうか!? 早くDjango1.1系から脱却したいものですなあ…