Django admin inline, обусловленный значениями полей модели

Я пытаюсь показать один из трех различных инлайнов дочерней модели для родительской модели, основываясь на значении выбранного поля в родительской модели. Я перепробовал все решения, которые всплывают в различных поисковых запросах Google, но, похоже, ничего не работает.

Сначала немного предыстории, я новичок в python и django, но пока что я чувствую, что быстро учусь. Я пытаюсь создать веб-приложение для размещения информации, связанной с различными пространственными местоположениями. Тип геометрии (geom_type) для каждого местоположения может быть разным (т.е. возможны точки, линии и полигоны). Для сбора этой информации я планирую создать родительскую модель (Location) для хранения имени и геом_типа (и, возможно, других метаданных). Пространственные данные, относящиеся к каждому местоположению, будут храниться в трех отдельных дочерних моделях, по одной для каждого геом_типа. При вводе данных я хотел бы создать новое местоположение и выбрать тип геома, который затем подтянет нужные данные в строку.

Теперь о деталях:

Модели

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)

Все три инлайна правильно отображаются в приведенном выше коде, как и ожидалось. Однако, когда я пытаюсь включить условную логику с различными вариациями get_inlines или get_inline_instances, всегда отображается только строка, связанная с последним утверждением "else".

Моя неудачная попытка

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

Я полагаю, что проблема возникает из-за того, что условные операторы неправильно ссылаются на поле модели. Но я никак не могу найти правильный способ достижения ожидаемого результата.

Используйте related_name в модели, как показано ниже:

next_question = models.ForeignKey(Question, on_delete=models.CASCADE, null = True, blank = True, related_name='next_question', limit_choices_to={'is_active': True})

и затем fk_name Как в примере ниже: Затем попробуйте. Надеюсь, вы сможете найти решение самостоятельно.

class Labels(admin.TabularInline):
    model = Label
    extra = 0
    fk_name = "next_question"

Используйте admin.StackedInline для OneToOne и admin.TabularInline для ForeignKey.

class ProfileInline(admin.StackedInline):
    model = Profile
    can_delete = False  

Создайте отдельную админку для 'Geometry' и 'Location', если вы их складываете.

Вернуться на верх