如何从模型库到Django中的派生类?

sla*_*acy 8 django django-models

假设一组简单的继承Model类,如下所示:

class BaseObject(models.Model): 
    some_field = models.SomeField(...)

class AwesomeObject(BaseObject): 
    awesome_field = models.AwesomeField(...)

class ExcellentObject(BaseObject): 
    excellent_field = models.ExcellentField(...)
Run Code Online (Sandbox Code Playgroud)

和一个如下所示的查询:

found_objects = BaseObject.objects.filter(some_field='bogus')
Run Code Online (Sandbox Code Playgroud)

获取每个found对象并将其转换为派生类的最佳方法是什么?我现在使用的代码是这样的:

for found in found_objects:
    if hasattr(found, 'awesomeobject'): 
        ProcessAwesome(found.awesomeobject)
    elif hasattr(found, 'excellentobject'): 
        ProcessExcellent(found.excellentobject): 
Run Code Online (Sandbox Code Playgroud)

但是,感觉这是滥用"hasattr".有没有更好的方法来做到这一点,而不在基类上创建一个显式的"类型"字段?

vdb*_*oor 5

对于这个特定问题,有django-polymorphic。它的工作原理是使用 Django 中的内容类型框架来存储派生表指向的模型 ID。当您评估查询集时,它将向上转换所有模型的特定类型。

你会得到:

>>> BaseProject.objects.all()
[ <AwesomeObject>, <ExcellentObject>, <BaseObject>, <AwesomeObject> ]
Run Code Online (Sandbox Code Playgroud)


Chr*_*att 4

这是我所知道的最好的方法。不幸的是,继承在这方面有点笨拙。多表继承基本上只是父模型和子模型添加的额外字段之间的一对一关系,这就是该hasattr技巧起作用的原因。您可以将其中每一个视为OneToOneField父模型的属性。当您这样想时,Django 无法知道要返回哪个子级,甚至无法知道是否返回子级,因此您必须自己处理该逻辑:

我倾向于在父级上创建一个方法,例如get_child,它只是循环遍历属性并返回弹出的属性:

class BaseObject(models.Model):
    some_field = models.SomeField(...)

    def get_child(self):
        if hasattr(self, 'awesomeobject'): 
            return ProcessAwesome(found.awesomeobject)
        elif hasattr(self, 'excellentobject'): 
            return ProcessExcellent(found.excellentobject):
        else:
            return None
Run Code Online (Sandbox Code Playgroud)

至少到那时,您只需拨打电话found.get_child(),也许就可以忘记那些让您到达那里的黑客行为了。