django管理员中的多态行为

时间:2011-04-26 17:11:22

标签: django django-models django-admin

问题

假设我有三个类A,B和C,其中B是A的子类,C是B的子类:

A <- B <- C

当我打开管理员并列出所有“A”时,我看到所有“A”,“B”和“C”。但是,当我按照其中一个链接,查看详细信息并编辑特定B时,我将只看到B的字段,即使该实例实际上是C的实例。 我希望看到的是根据其最具体的类型向我展示的对象。

我正在尝试

我正在使用InheritanceManager来获取在更抽象级别工作时转换为正确类型的实例。这几乎很好用(它不能处理多个继承级别)。但是,即使对于单个继承级别,我也无法将多态行为反映在管理员中,因为显然管理员不知道管理器的select_subclasses()方法。

我有什么想法可以用来在管理员身上获得类似多态的行为吗?

具体示例

models.py:

from django.db import models
from model_utils.managers import InheritanceManager

class A(models.Model):
    a_field = models.CharField(max_length=200)
    objects = InheritanceManager()

class B(A):
    b_field = models.CharField(max_length=200)

class C(B):
    c_field = models.CharField(max_length=200)

admin.py

from myapp.models import A, B, C
from django.contrib import admin

admin.site.register(A)
admin.site.register(B)
admin.site.register(C)

更新

添加一个来自2010年的两个主题的链接,并考虑如何使用django-polymorphic实现这一点:

1 个答案:

答案 0 :(得分:2)

这个答案是不完整的,因为我无法重现您的第一个问题。当我列出父模型对象时,我会看到所有这些对象。 (或者可能存在一些误解。)


可以使用admin inline部分解决不完整字段的问题。由于子类只是具有隐式OneToOneField到父模型的模型,因此您可以为“C”定义内联,然后将其包含在B管理员的inlines属性中。

问题是:

  • 用户将无法通过B管理员的内联创建“C”类对象;它只能通过C的管理员来完成。它只是观看。
  • 它不适用于多个继承级别:您可以将B作为内联包含在A的管理员中,但我知道没有简单的方法可以将C包含为内联到B的内联。

另一种方法是修改A的管理模板,在那里放置一个指向真实实例的链接(无论是B还是C)。但我想你已经想过了。


关于上一期:如果要修改某个模型管理员的查询集,可以通过ModelAdmin的queryset()方法完成(参见this question中的示例)。您可以在模型的管理员上覆盖此方法,并在其中放置select_subclasses()逻辑。但是我没有尝试过,所以如果你这样做,我不能说ModelAdmin的行为是什么。也许你需要覆盖更多的方法。


PS。我目前使用django-polymorphic,从事具体继承的类似项目。它没有提供任何管理多态模型的方法,所以我决定不再依赖Django的管理员,只为站点人员创建一个简单的自定义界面,我想这不会花费太多时间。