代码之家  ›  专栏  ›  技术社区  ›  Dave Vogt

如何获取django模型的子类对象

  •  2
  • Dave Vogt  · 技术社区  · 15 年前

    当我有一个这样的Django模型类时:

    class BaseClass(models.Model):
         some_field = models.CharField(max_length = 80)
         ...
    

    以及它的一些子类,例如

    class SomeClass(BaseClass):
         other_field =  models.CharField(max_length = 80)
    

    然后我知道我可以通过调用

    base  = BaseClass.objects.get(pk=3)
    my_obj= base.someclass
    

    现在问题出现了,我有多个子类,我所拥有的只是一个基类的实例。在不预先知道子类对象是类的情况下,如何才能到达该子类对象?


    其思想是加载一个相应的视图,并让它完成这些工作。对于这些模型,我的项目功能只有一组有限的默认操作,如视图、编辑、删除等。我不希望通过URL公开给定对象的类型,因此“常规方式”不可用。

    4 回复  |  直到 10 年前
        1
  •  3
  •   Daniel Roseman    15 年前

    没有内置的方式。

    也许最好的办法是定义一个 derived_type 基类上的字段,该字段在派生类保存时自动设置。然后你可以有一个 get_derived 方法,该方法基于检查 派生型 并返回实际派生对象。

        2
  •  2
  •   John Millikin    15 年前

    在不预先知道子类对象是类的情况下,如何才能到达该子类对象?

    为什么这会有用?如果您不知道您想要什么类,那么您也将不知道要调用哪些方法,或者可以检查哪些属性。


    其思想是加载一个相应的视图,并让它完成这些工作。对于这些模型,我的项目功能只有一组有限的默认操作,如视图、编辑、删除等。我不希望通过URL公开给定对象的类型,因此“常规方式”不可用。

    如果您提前知道一组模型子类,或者愿意在中心视图列表中注册它们,那么可以这样做:

    VIEWS = [('subclass_a', a_views), ('subclass_b', b_views)]
    
    def edit(request):
        base = (get base somehow)
    
        for attrname, views in VIEWS:
            if getattr(base, attrname) is not None:
                return views['edit']
    

    根据您有多少种不同类型的视图,您可以将搜索抽象为一个单独的函数,因此最终视图如下所示:

    def edit(request):
        return generic_base_view(request, 'edit')
    
        3
  •  2
  •   michel.iamit    12 年前

    对于在问题发布和给出接受的答案之后才查看此答案的人,在新版本的Django中,这更直接,请参见: django documentation about multi table inheritance

    看看地方和餐馆的例子。基对象是一个地方,子类是一个餐馆。你可以通过place.restaurant得到子类,如果这个地方不是一个餐馆,你可以得到一个例外。 我添加这个是因为接受的答案可能有点过时,并导致我走错了轨道。

        4
  •  0
  •   Rebecca Meritz    10 年前

    如果使用django model utils中的inheritancemanager,则可以在查询时选择子类,而不必知道它们提前了什么。

    https://django-model-utils.readthedocs.org/en/latest/managers.html#inheritancemanager