【问题标题】:Showing json field in Django admin在 Django admin 中显示 json 字段
【发布时间】:2018-06-17 04:16:07
【问题描述】:

我有一个 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

并且在data字段中我存储了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

知道怎么做吗?

【问题讨论】:

    标签: python json django


    【解决方案1】:

    我在 Django Admin (Django>=3.1) 中为 JSONField 添加基本格式的解决方案:

    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

    from django.contrib.postgres.fields import JSONField 
    

    希望对你有帮助!

    【讨论】:

    • 谢谢。真正干净的解决方案。
    • 在字段只读但不应用于 readonly_fields 中定义的 JSONField 时有效。
    • 对于任何使用 django 3.X 和 JSONField(来自 django 的默认字段)在您的 models.py 中尝试此操作的人,您必须使用 from django.db.models import JSONField 而不是 django.contrib.postgres.fields import JSONField
    【解决方案2】:

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

    它奏效了。

    【讨论】:

    • 就我而言,它可以在没有 json.loads 的情况下工作:data = instance.data
    【解决方案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'
    

    【讨论】:

      【解决方案4】:

      为了在管理页面中显示格式化的 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},
          }
      

      【讨论】:

      • 你使用 postgres 吗?此解决方案仅在您使用 postgres 时有效。 @弗洛伦特
      • 我的代码一定有问题和/或我不明白如何配置 admin.py
      • 与我分享一些代码,我会尽力帮助你。 @弗洛伦特
      猜你喜欢
      • 2021-04-28
      • 1970-01-01
      • 1970-01-01
      • 2013-08-28
      • 2021-09-18
      • 2023-01-03
      • 2021-10-18
      • 1970-01-01
      • 2011-08-16
      相关资源
      最近更新 更多