django的Admin中的多态行为 [英] Polymorphic behavior in django's Admin

查看:283
本文介绍了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。注册(A)
admin.site.register(B)
admin.site.register(C)






更新



从2010年的两个线程添加链接关于如何用django-polymorphic来实现这一点的一些想法:




解决方案

这个答案是部分的,因为我无法重现你的第一个问题。当我列出父模型对象时,我看到所有的对象。 (或者也许有一些误会)。






不完整字段的问题可以通过管理员内联部分解决。由于子类只是一个隐含的OneToOneField到父模型的模型,所以您可以为C定义一个内联,然后将其包含在B的管理员的 inlines 属性中。



问题是:




  • 用户将无法创建类的对象 C通过B的管理员内联;它只能通过C的管理员完成。它只能查看。

  • 它不适用于多个继承级别:您可以将B包含在A的管理员中作为内联,但我知道没有简单的方法将C作为内联包含到B的在线。



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






关于上一个问题:如果你想修改一些型号的管理员的查询,可以通过ModelAdmin的 queryset()方法(请参阅这个问题)。您可以在模型的管理员上覆盖此方法,并在其中放置 select_subclasses()逻辑。但是我没有尝试过,所以我不能说如果你这样做是ModelAdmin的行为。也许你需要重写更多的方法。






PS。我目前使用 django-polymorphic ,在类似的项目中进行具体的继承。它不提供任何方式通过管理员来管理多态模型,所以我决定不要依赖Django的管理员,只需为站点工作人员创建一个简单的自定义界面,我想这不会花太多时间。 p>

The problem

Suppose I have three classes A, B and C, where B is a subclass of A and C is a subclass of B:

A <- B <- C

When I open up the admin and list all "A"s, I see all "A"s, "B"s and "C"s. But when I follow one of those links, to see the details and edit that particular B, I will see only the fields of B, even if that instance is actually an instance of C. What I would like to see is the object to be shown to me according to its most specific type.

What I'm trying

I'm using InheritanceManager to get instances casted to the right type when working at a more abstract level. This works almost well (it can't handle more than one inheritance level). However, even for a single inheritance level, I can't get the polymorphic behavior to be reflected in the admin, as obviously the admin doesn't know about the manager's select_subclasses() method.

Any idea on how could I use to get such a polymorphic-like behavior on the admin?

Concrete Example

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)


Update

Adding a link to two threads from 2010 with some thoughts on how to achieve this with django-polymorphic:

解决方案

This answer is partial, since I can't reproduce your first issue. When I list parent model objects, I see all of them. (Or maybe there's some misunderstanding.)


The issue with incomplete fields can be partially solved with admin inline. Since the subclass is simply a model with implicit OneToOneField to parent model, you can define an inline for "C" and then include it into inlines attribute on B's admin.

The problems are:

  • User won't be able to create object of class "C" via an inline in B's admin; it could be done only via C's admin. It's viewing only.
  • It won't work with multiple inheritance levels: you can include B into A's admin as an inline, but I know no easy way to include C as an inline to B's inline.

Another way is to modify A's admin template, placing there a link to the real instance (be it B or C). But I suppose you've already thought of it.


Regarding last issue: if you want to modify some model admin's queryset, it can be done via ModelAdmin's queryset() method (see an example in this question). You can override this method on your model's admin and place select_subclasses() logic there. But I haven't tried it so I can't say what would be ModelAdmin's behaviour if you do this. Maybe you'll need to override a few more methods.


PS. I currently use django-polymorphic, working on similar project with concrete inheritance. It doesn't provide any means to manage polymorphic models via admin either, so I decided not to rely much on Django's admin for this and just create a simple custom interface for site staff, I guess it won't take much time.

这篇关于django的Admin中的多态行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆