在Django管理后台显示JSON字段

25

我有一个Django模型如下:

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

在数据字段中,我存储JSON数据,如下所示:

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

我希望在Django管理面板中仅显示该字段的URL。

现在我有:

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

admin.site.register(BodyHeight, BodyHeightAdmin)
那是没有数据字段的。如果我在list_display中添加data字段,它会显示整个json(丑陋的格式),但我只想要url。 有什么想法吗?
4个回答

57

我为在Django Admin中为JSONField添加基本格式的解决方案(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}
    }

使用方法:

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

对于 Django < 3.1,您需要以以下方式导入 JSONField:

from django.contrib.postgres.fields import JSONField 

希望这能帮到你!


4
谢谢。解决方案非常简洁。 - Cyrille Pontvieux
7
只有在字段不是只读时才起作用,但不适用于在“readonly_fields”中定义的JSON字段。 - monkut
2
对于任何尝试在Django 3.X中使用JSONField(来自Django的默认JSONField)的人,在您的models.py文件中,您需要使用from django.db.models import JSONField而不是django.contrib.postgres.fields import JSONField - hansTheFranz
只能读字段有什么解决方案吗? - 404usernamenotfound

12

我将 bodyHeightAdmin 类修改如下:

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"]

它起到了作用。


1
对于我的情况,它可以在不使用json.loads的情况下工作:data = instance.data - ElRey777
这对我起作用:def my_field_name(self, instance) return instance.my_json_field["my_field_name"] - Harry Moreno

3
这是一个适用于JSONField只读设置的示例。
# 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'

2
为了在管理页面中显示格式化的JSON,我建议您使用Python库django-json-widget。它易于使用并具有出色的功能(您可以编辑格式化的JSON)。
1)安装库pip install django-json-widget 2)将django-json-widget添加到settings.py中的installed_apps中。
INSTALLED_APPS = (
    ...
    'django_json_widget',
    ...
)

3) 在admin.py中添加以下代码(不要忘记将YourModel更改为您实际的模型名称)

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},
    }

1
你使用Postgres吗?只有在使用Postgres时,此解决方案才有效。@Florent - Mihael Waschl
我的代码肯定有问题,或者我不理解如何配置admin.py文件。 - Florent
分享一些代码给我,我会尽力帮助你。@Florent - Mihael Waschl
1
此软件包最近一次更新于2021年,支持 Django <= 2.2。 - dannydedog
2
当升级到最新的Django 4.2 LTS版本时,此软件包会出现故障。 - kunambi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接