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

Django Admin:根据父模型字段值动态显示对应子模型Inline

动态显示Django Admin Inline:根据Geometry类型匹配对应子模型

我是Python和Django新手,正在开发存储空间位置信息的Web应用。父模型Location关联Geometry模型(包含Point、Linestring、Polygon三种几何类型),对应三个子模型Point、Linestring、Polygon分别存储不同类型空间数据。

希望在Django Admin中创建Location实例时,根据所选geom_type字段值动态显示对应子模型Inline。当前代码会显示全部三个Inline,尝试通过get_inlines实现条件逻辑时,始终仅显示else分支结果,推测是字段引用方式错误,求正确实现方法。

模型代码

from django.contrib.gis.db import models

class Geometry(models.Model):

    TYPE = (
    ('Point', 'Point'),
    ('Linestring', 'Linestring'),
    ('Polygon', 'Polygon'),
    )

    geom_type = models.CharField('Geometry Type', choices = TYPE, max_length = 30)

    class Meta:
        verbose_name = 'Geometry'
        verbose_name_plural = 'Geometries'

    def __str__(self):
        return self.geom_type

class Location(models.Model):
    name = models.CharField('Location Name', max_length = 50)
    geom_type = models.ForeignKey(Geometry, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

class Point(models.Model):
    name = models.OneToOneField(Location, on_delete=models.CASCADE)
    geometry = models.PointField()
    
    def __str__(self):
        return self.name.name

class Linestring(models.Model):
    name = models.OneToOneField(Location, on_delete=models.CASCADE)
    geometry = models.LineStringField()

    def __str__(self):
        return self.name.name

class Polygon(models.Model):
    name = models.OneToOneField(Location, on_delete=models.CASCADE)
    geometry = models.PolygonField()

    def __str__(self):
        return self.name.name

Admin代码

from django.contrib.gis import admin
from leaflet.admin import LeafletGeoAdmin, LeafletGeoAdminMixin
from .models import Geometry, Location, Point, Linestring, Polygon
   
class GeometryAdmin(admin.ModelAdmin):
    list_display = ('id', 'geom_type')

admin.site.register(Geometry, GeometryAdmin)

class PointInline(LeafletGeoAdminMixin, admin.StackedInline):
    model = Point

class LinestringInline(LeafletGeoAdminMixin, admin.StackedInline):
    model = Linestring

class PolygonInline(LeafletGeoAdminMixin, admin.StackedInline):
    model = Polygon

class LocationAdmin(admin.ModelAdmin):
    model = Location
    list_display = ('id', 'name', 'geom_type')
    inlines = [
        PointInline,
        LinestringInline,
        PolygonInline
    ]
       
admin.site.register(Location, LocationAdmin)

失败的尝试代码

def get_inlines(self, request, obj: Location):
    if obj.geom_type == 'Point':
        return [PointInline]
    elif obj.geom_type == 'Location':
        return [LinestringInline]
    elif obj.geom_type == 'Polygon':
        return [PolygonInline]
    else:
        return []

解决方法

你失败的核心问题有两个:

  1. obj.geom_type是Geometry模型的实例,不是字符串,直接和字符串比较永远不成立,会走到else分支;
  2. elif分支里把Linestring误写成了Location。

修改后的LocationAdmin代码如下:

class LocationAdmin(admin.ModelAdmin):
    model = Location
    list_display = ('id', 'name', 'geom_type')

    def get_inlines(self, request, obj=None):
        # 创建新实例时,obj为None,先不显示任何Inline
        if not obj:
            return []
        # 获取关联Geometry实例的geom_type字符串值
        selected_type = obj.geom_type.geom_type
        if selected_type == 'Point':
            return [PointInline]
        elif selected_type == 'Linestring':
            return [LinestringInline]
        elif selected_type == 'Polygon':
            return [PolygonInline]
        else:
            return []

补充说明

  • 上述代码在编辑已有Location实例时可以正常动态显示对应Inline;
  • 如果希望在创建新Location时,选择geom_type后实时显示对应Inline,需要借助JavaScript实现动态刷新(因为创建时obj还未保存,服务器端无法获取选择值)。新手可以先实现编辑场景的功能,再逐步优化创建流程。

内容的提问来源于stack exchange,提问作者fishdata

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 20:15:38