Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Showing json field in Django admin

I have an Django model as follows:

class BodyHeight(models.Model):
    seats = models.ForeignKey(to=Seats)
    name = models.CharField(max_length=127, null=True, blank=True)
    key = models.CharField(max_length=100, null=True)
    data = models.TextField(null=True, blank=True)

    class Meta:
        verbose_name_plural = "Body heights"

    def __str__(self):
        return self.name

And in the data field I store the json data, as follows:

{"url": "https://some_url=/BE?category=COMMERCIAL, "images": ["url_to_some_image"]}

And I want to show in the Django admin panel only the url from that field.

Now I have:

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

admin.site.register(BodyHeight, BodyHeightAdmin)

That is without the data field. If I add the data field in list_display it shows than whole json (ugly format), but I want only the url.

Any idea how to do that?

like image 560
Boky Avatar asked Jan 08 '18 07:01

Boky


2 Answers

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!

like image 124
Valar Avatar answered Sep 21 '22 07:09

Valar


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.

like image 41
Boky Avatar answered Sep 18 '22 07:09

Boky