Django:没有数据库查询的多表继承和upcasting

时间:2012-12-19 18:22:58

标签: django django-models

简短版本:

在Django中使用多表继承,给定派生类的模型对象,是否可以获得相应的基类模型对象,而无需进行额外的数据库查询?

长版:

我在Django应用程序中使用多表继承。我有一种情况,基类定义了派生类重写的某些方法,但实际上我想调用基类方法。这是一个例子:

from django.db import models

class Animal(models.Model):
    name = models.CharField(max_length=100)

    def speak(self):
        return "generic animal noise"

    def foo(self):
        ...

    def bar(self):
        ...

    def baz(self):
        ...


class Dog(Animal):
    breed = models.CharField(max_length=100)

    def speak(self):
        return "Arf"

    def foo(self):
        ...

    def bar(self):
        ...

    def baz(self):
        ...

我有一个类型为Dog的模型对象的引用,我想在其上调用Animal.speak方法,而不是Dog.speak方法。我知道我可以这样做:

dog = Dog.objects.get(name="rover")
Animal.speak(dog)

但是,在我写的代码中,有多个方法被覆盖,我需要调用,所以不要这样做:

Animal.foo(dog)
Animal.bar(dog)
Animal.baz(dog)
...

我希望能够进行向上转换,然后让所有调用都解析为基类的方法:

animal = upcast_to_animal(dog)
animal.foo()
animal.bar()
animal.baz()

我知道实现upcast_to_animal的一种方法,但它需要进行数据库查询:

def upcast_to_animal(x):
    return Animal.objects.get(pk=x.pk)

我的问题是:是否可以在不对数据库进行额外查询的情况下实现“upcast_to_animal”方法?

2 个答案:

答案 0 :(得分:4)

只是一个简单的演示(向上演示):

class Animal(models.Model):
    name = models.CharField(max_length=30)

    def foo(self):
        print 'hello animal'

class Dog(Animal):
    name_me = models.CharField(max_length=30)

    def foo(self):
        print 'hello dog'

# django shell        
>>> dog = Dog.objects.create(name_me='bull dog')
>>> dog.foo()
hello dog
>>> animal = super(dog.__class__, dog)
>>> animal.foo()
hello animal

答案 1 :(得分:0)

怎么样:

import copy

animal = copy.deepcopy(dog)
animal.__class__ = Animal