2012-12-19 70 views
1

短版:Django的:多表繼承和上溯造型沒有數據庫查詢

隨着在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): 
     ... 

我不得不類型狗的模型對象的引用,我要打電話就可以了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」方法而不額外查詢數據庫?

回答

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 
0

如何:

import copy 

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