如何在Django Admin详情页以列表形式展示子对象?
Django Admin中以只读列表形式展示关联的Setting对象
问题背景
我有Setting和SettingsGroup两个模型,希望在SettingsGroup的详情/编辑页中,以带跳转链接的只读列表展示关联的Setting对象,而非InlineModelAdmin默认的可编辑表单——毕竟表单占用空间太大,我不需要从父页面编辑子对象,只需要快速查看并能跳转到子对象页面即可。
模型代码
Setting模型
class Setting(models.Model): key = models.CharField(max_length=255, blank=False) value = models.TextField(blank=True) group = models.ForeignKey('SettingsGroup', blank=True, on_delete=models.SET_NULL, null=True) def __str__(self): return str(self.key)
SettingsGroup模型
class SettingsGroup(models.Model): name = models.CharField(max_length=255) description = models.TextField(blank=True) def __str__(self): return str(self.name)
当前尝试的实现(不符合需求)
我试过用InlineModelAdmin,但它会渲染成可编辑表单,而且原代码存在拼写错误,修正后如下:
class SettingsGroupInline(admin.StackedInline): # 原代码笔误:StackedInlin → StackedInline model = Setting fk_name = 'group' @admin.register(SettingsGroup) class SettingsGroupAdmin(admin.ModelAdmin): inlines = [SettingsGroupInline, ] # 原代码笔误:SettingGroupsInline → SettingsGroupInline
预期效果
- 打开
SettingsGroup实例MySettings的编辑页时,上方显示MySettings的常规编辑表单; - 下方仅展示关联的
CoolSetting(只读列表形式,带跳转至该Setting编辑页的链接); - 未关联的
BoringSetting不会显示。
现成解决方案
不用重复造轮子,Django原生或简单自定义就能实现:
方法1:用原生只读内联(最简便)
Django自带ReadOnlyInlineModelAdmin,直接设置成只读模式,会自动生成子对象的跳转链接,且展示紧凑:
from django.contrib import admin class SettingReadOnlyInline(admin.ReadOnlyInlineModelAdmin): model = Setting fk_name = 'group' can_delete = False fields = ('key', 'value',) # 指定要展示的字段,字段值会自动链接到对应Setting的编辑页 extra = 0 # 隐藏添加新记录的表单 @admin.register(SettingsGroup) class SettingsGroupAdmin(admin.ModelAdmin): inlines = [SettingReadOnlyInline, ]
方法2:自定义只读字段(更灵活)
如果想要完全自定义展示样式,比如添加额外信息,可以在SettingsGroupAdmin中手动渲染关联列表:
from django.contrib import admin from django.urls import reverse from django.utils.html import format_html @admin.register(SettingsGroup) class SettingsGroupAdmin(admin.ModelAdmin): readonly_fields = ('related_settings',) def related_settings(self, obj): settings = obj.setting_set.all() if not settings: return "无关联设置" # 生成带跳转链接的列表项 link_items = [] for setting in settings: edit_url = reverse('admin:your_app_setting_change', args=(setting.id,)) link = format_html('<a href="{}">{}</a> (值:{})', edit_url, setting.key, setting.value) link_items.append(f'<li>{link}</li>') return format_html('<ul>{}</ul>', ''.join(link_items)) related_settings.short_description = "关联设置"
这里把your_app换成你实际的应用名称即可,这种方式可以自由调整展示的内容和样式。
方法3:第三方包(可选,用于进阶需求)
如果需要可切换编辑/只读模式的交互,可以用django-admin-inline-paginator这类包,但基础需求用前两种原生方法完全足够。
内容的提问来源于stack exchange,提问作者Dave Mackey
相关产品推荐
相关产品推荐

