使用django,我如何从超类对象实例构造代理对象实例?

Bub*_*kin 5 python django django-models

我仍然对代理模型与django中的超类之间的关系感到困惑.我现在的问题是如何从已经检索到的超类实例中获取代理模型的实例?

所以,让我说我有:

class Animal(models.Model):
   type = models.CharField(max_length=20)
   name = models.CharField(max_length=40)

class Dog(Animal):  
   class Meta:
       proxy = True

   def make_noise(self):  
       print "Woof Woof"  

Class Cat(Animal):  
   class Meta:
       proxy = True

   def make_noise(self):  
       print "Meow Meow"

animals = Animal.objects.all()
for animal in animals:
   if (animal.type == "cat"):
      animal_proxy = # make me a cat
   elif (animal.type == "dog"):
      animal_proxy = # make me a dog
   animal_proxy.make_noise()
Run Code Online (Sandbox Code Playgroud)

好.那么......"让我成为一只猫"的内容不需要回溯到数据库,例如:

animal_proxy = Cat.objects.get(id=animal.id)
Run Code Online (Sandbox Code Playgroud)

有没有一种简单的方法从Animal的一个实例创建一个Cat实例,我知道它是一只猫?

Man*_*dan 6

您正在尝试为继承层次结构实现持久性.使用一个具体的表和一个type开关是一个很好的方法来做到这一点.但是我认为你的实现,特别是:

for animal in animals:
   if (animal.type == "cat"): 
      animal_proxy = # make me a cat
Run Code Online (Sandbox Code Playgroud)

正在违背Django的粮食.开启类型不应该与代理(或模型)类无关.

如果我是你,我会做以下事情:

首先,在代理模型中添加"类型感知"管理器.这将确保Dog.objects始终Animal使用type="dog"Cat.objects获取Animal实例来获取实例type="cat".

class TypeAwareManager(models.Manager):
    def __init__(self, type, *args, **kwargs):
        super(TypeAwareManager, self).__init__(*args, **kwargs)
        self.type = type

    def get_query_set(self):
        return super(TypeAwareManager, self).get_query_set().filter(
              type = self.type)

class Dog(Animal):
    objects = TypeAwareManager('dog')
    ...

class Cat(Animal):
    objects = TypeAwareManager('cat')
    ...
Run Code Online (Sandbox Code Playgroud)

其次,分别获取子类实例.然后,您可以在操作之前将它们组合在一起.我曾经itertools.chain把两个结合起来Querysets.

from itertools import chain
q1 = Cat.objects.all() # [<Cat: Daisy [cat]>]

q2 = Dog.objects.all() # [<Dog: Bruno [dog]>]

for each in chain(q1, q2): 
    each.make_noise() 

# Meow Meow
# Woof Woof
Run Code Online (Sandbox Code Playgroud)