Showing json field in Django admin

I changed the bodyHeightAdmin class as follows:

class BodyHeightAdmin(admin.ModelAdmin):
    search_fields = ('name', )
    list_display = ('id', 'name', 'key', 'url', )
    list_display_links = ('id', 'name', 'key', )

    def url(self, instance):
        data = json.loads(instance.data)
        return data["url"]

And it worked.


My solution for adding basic formatting for JSONField in Django Admin (Django>=3.1):

import json
import logging

from django.db.models import JSONField 
from django.contrib import admin
from django.forms import widgets


logger = logging.getLogger(__name__)


class PrettyJSONWidget(widgets.Textarea):

    def format_value(self, value):
        try:
            value = json.dumps(json.loads(value), indent=2, sort_keys=True)
            # these lines will try to adjust size of TextArea to fit to content
            row_lengths = [len(r) for r in value.split('\n')]
            self.attrs['rows'] = min(max(len(row_lengths) + 2, 10), 30)
            self.attrs['cols'] = min(max(max(row_lengths) + 2, 40), 120)
            return value
        except Exception as e:
            logger.warning("Error while formatting JSON: {}".format(e))
            return super(PrettyJSONWidget, self).format_value(value)


class JsonAdmin(admin.ModelAdmin):
    formfield_overrides = {
        JSONField: {'widget': PrettyJSONWidget}
    }

Usage:

admin.site.register(models.MyModel, JsonAdmin)

For Django < 3.1 you have to import JSONField in this way:

from django.contrib.postgres.fields import JSONField 

Hope it will help you!


Here's a case valid for when the JSONField is set for readonly

# set 'url' editable=False in model defintion

class BodyHeightAdmin(admin.ModelAdmin):
    search_fields = ('name', )
    list_display = ('id', 'name', 'key', 'get_pprint_url', )
    list_display_links = ('id', 'name', 'key', )
    readonly_fields = ('get_pprint_url', )

    def url(self, instance):
        data = json.loads(instance.data)
        return data["url"]

    actions = [
        'process_webhook_events',
        'reset_webhook_events'
    ]

    def get_pprint_url(self, obj=None):
        result = ''
        if obj and obj.url:
            result = json.dumps(obj.url, indent=4, sort_keys=True)
            # keep spaces
            result_str = f'<pre>{result}</pre>'
            result = mark_safe(result_str)
        return result
    get_pprint_url.short_description = 'url'

To show formatted JSON in admin page I recommend you python library django-json-widget. It is easy to use and has great features (you can edit formatted JSON).

1) install library pip install django-json-widget

2) add django-json-widget to installed_apps in settings.py

INSTALLED_APPS = (
    ...
    'django_json_widget',
    ...
)

3) add following code to admin.py (do not forget to change YourModel with your real model name)

from django.contrib import admin
from django.contrib.postgres import fields
from django_json_widget.widgets import JSONEditorWidget
from .models import YourModel


@admin.register(YourModel)
class YourModelAdmin(admin.ModelAdmin):
    formfield_overrides = {
        fields.JSONField: {'widget': JSONEditorWidget},
    }