2011-04-26 70 views
2

问题在Django管理多态行为

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

A <- B <- C 

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

我使用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的多态:

回答

2

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


不完整字段的问题可以通过管理内联部分解决。由于子类只是一个带有隐式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的管理员,并为网站员工创建一个简单的自定义界面,我想这不会花费太多时间。

+0

我为这个问题增加了一个具体的例子。你是对的,列出所有的“A”也会列出“B”和“C”。我也相应地解决了这个问题,并为剩下的问题添加了更多细节。 – 2011-05-05 15:05:24

+0

感谢您的内联建议。我肯定可以解决一些使用它们的问题,但正如你所说,它们的适用性非常有限,而且你提出的问题不容忽视。 'queryset()'方法工作得很好,但它也只适用于单个级别(尽管如此,这更多是对'InheritanceManager'的限制)。 – 2011-05-05 15:19:01

+0

当然,忘记django-admin并从零开始做所有事情也是一种选择。我看到“免费”管理员是django的一大优点,但它开始看起来对这个项目有限制,因为它会广泛使用继承关系。 – 2011-05-05 15:24:16