You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Admin中实现类似Wagtail StreamField的模型选择功能

问题背景与需求

我定义了Cluster、Image、Description三个模型,对应的models.py代码如下:

class Cluster(models.Model):
    blockOption= (('IMG', 'IMG'),('DESC', 'DESC'),)
    block = models.CharField(max_length= 100, choices=blockOption)
    order= models.IntegerField(null=True)
    post = models.ForeignKey(Post, verbose_name=('Link to Post'), on_delete=models.CASCADE)
        
class Image(models.Model):
    src = models.ImageField(verbose_name=('Imagefile'))
    captions= models.CharField(max_length= 100, null=True)
    cluster = models.ForeignKey(Cluster, verbose_name=('Link to Post'), on_delete=models.CASCADE)

class Description(models.Model):
    text=models.TextField(max_length=400)
    cluster = models.ForeignKey(Cluster, verbose_name=('Link to Post'), on_delete=models.CASCADE)

在admin.py中,我将ImageAdminInline和DescriptionAdminInline设置为ClusterAdmin的内联模型,代码如下:

class ImageAdminInline(TabularInline):
    extra = 1
    model = Image
class DescriptionAdminInline(TabularInline):
    model= Description

@admin.register(Cluster)
class ClusterAdmin(admin.ModelAdmin):
    inlines= (ImageAdminInline, DescriptionAdminInline)

我希望通过ClusterAdmin实现类似Wagtail StreamField的效果:根据Cluster的block选项选择显示对应的内联模型,且不想重写Django Admin模板。此前尝试用Ajax隐藏/显示内联,但因修改模板失败,寻求可行解决方案。


可行解决方案

无需修改Django Admin模板,只需借助Admin的Media类注入自定义JavaScript,即可实现根据block选项切换显示对应内联的效果。

步骤1:修改ClusterAdmin添加媒体资源

在admin.py中为ClusterAdmin添加Media类,注入内联JS逻辑:

@admin.register(Cluster)
class ClusterAdmin(admin.ModelAdmin):
    inlines= (ImageAdminInline, DescriptionAdminInline)
    
    class Media:
        extra_js = [
            """
            document.addEventListener('DOMContentLoaded', function() {
                // 获取block选择框元素
                const blockSelect = document.getElementById('id_block');
                // 获取两个内联表单的容器(Django自动生成ID规则:{模型名小写}_set-group)
                const imageInlineContainer = document.getElementById('image_set-group');
                const descInlineContainer = document.getElementById('description_set-group');

                // 定义切换内联显示状态的函数
                function toggleInlineVisibility() {
                    const selectedBlock = blockSelect.value;
                    if (selectedBlock === 'IMG') {
                        imageInlineContainer.style.display = 'block';
                        descInlineContainer.style.display = 'none';
                    } else if (selectedBlock === 'DESC') {
                        imageInlineContainer.style.display = 'none';
                        descInlineContainer.style.display = 'block';
                    } else {
                        // 默认状态:都隐藏(可根据需求调整)
                        imageInlineContainer.style.display = 'none';
                        descInlineContainer.style.display = 'none';
                    }
                }

                // 页面加载完成后初始化显示状态
                toggleInlineVisibility();
                // 监听选择框变化,实时切换内联显示
                blockSelect.addEventListener('change', toggleInlineVisibility);
            });
            """,
        ]

步骤2:验证内联容器ID

Django Admin为内联表单生成的容器ID遵循{模型名小写}_set-group规则:

  • Image模型的内联容器ID为image_set-group
  • Description模型的内联容器ID为description_set-group

如果不确定ID,可通过浏览器开发者工具(F12)查看页面元素确认。

效果说明

  • 页面加载时,会根据当前block字段的选中值自动显示对应内联表单,隐藏另一个。
  • 切换block选项时,内联表单会实时切换显示状态。
  • 完全无需修改Django Admin模板文件,仅通过Admin自带的媒体注入功能实现需求。

内容的提问来源于stack exchange,提问作者Hyung Do Kim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 01:40:37