DjangoAdminでJSONFieldの編集がunicode変換されてしまう問題

JSONFieldの値に日本語が入ってると文字化け

DjangoAdminの編集画面では、JSONFieldの値に日本語が入っていると文字化けして、unicodeになってしまいます。

そこで、以下のような形で、JSONField用にFormを作ってあげる必要があります。

import json
from django.contrib.postgres.forms.jsonb import InvalidJSONInput, JSONField

class ReadableJSONFormField(JSONField):
    def prepare_value(self, value):
        if isinstance(value, InvalidJSONInput):
            return value
        return json.dumps(value, ensure_ascii=False, indent=4)

ModelFormでFieldをoverrideする

使い方としては幾つかあります。まずはModelFormでモデルのFieldをoverrideする方法です。

上記で作成した、ReadableJSONFormFieldを使用してFieldを上書いてあげます。そうすることで、編集時も日本語が正しく表示されます。

from django import forms

class ExampleForm(forms.ModelForm):
    samples = ReadableJSONFormField(required=False)

    class Meta:
        models = Examples
        fields = (samples,)

ModelAdminでFieldをoverrideする

続いては、ModelAdminでJSONField全てに対してformを上書きする方法です。

やり方は簡単で、JSONFieldのform_classにReadableJSONFormFieldを与えてあげるだけで、編集時も日本語が正しく表示されます。

from django.contrib import admin

@admin.register(Examples)
class ExampleAdmin(admin.ModelAdmin):
    formfield_overrides = {
        JSONField: {'form_class': ReadableJSONFormField},
    }

ModelのJSONFieldのサブクラスを作成してformfield関数をoverrideする

最後にJSONFieldのサブクラスを作ってしまい、全モデルのJSONFieldで使うといった方法です。

モデルのJSONFieldのformfield関数でセットされているform_classを置き換えてあげます。そうすることで、モデルでJSONFieldを使う場合には、こちらのReadableJSONFieldを使えばAdmin側でも問題なく、日本語が表示されるようになります。

from django.contrib.postgres.fields import JSONField

class ReadableJSONField(JSONField):
    def formfield(self, **kwargs):
        return super().formfield(**{
            'form_class': ReadableJSONFormField,
            **kwargs,
        })

最後に

色々なところで置き換えれることも分かり、勉強になりました。

どのレイヤーでformを書き換えてあげるかですが、モデルで使う用のサブクラスを一個作っておくと楽で良いんじゃないかなぁと思います。

コメントを残す