2015-03-03 4 views
1

У меня есть реальный случай жизни, который можно решить с помощью полиморфизма, как в Java Где мы можем создать список объектов, принадлежащих тому же типу. Однако у каждого объекта могут быть переопределенные или дополнительные поля.Доступ к дочерним методам в Python Django

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

    def speak(self): 
     return "I am an animal" 


class Cat(Animal): 

    def speak(self): 
     """ OVERRIDE """ 
     return "MEAOO" 


class Dog(Animal): 

    def speak(self): 
     """ OVERRIDE """ 
     return "WOOOOF" 

Теперь мне нужно получить всех животных, но пусть каждое животное будет использовать его метод говорения. Я не смог сделать это, как показано ниже.

>>> c = Cat(name="MyCAT") 
>>> c.save() 
>>> d = Dog(name="MyDOG") 
>>> d.save() 
>>> animals = Animal.objects.all() 
>>> animals 
[<Animal: Animal object>, <Animal: Animal object>] 
>>> for a in animals: 
...  a.speak() 
... 
'I am an animal' 
'I am an animal' 
>>> 

Для меня выход должен быть как ниже

'MEAOO' 
'WOOOOF' 

Есть в любом случае, чтобы сделать подобную вещь в Django?

+3

Это потому, что вы вытаскиваете животных из объекта «Животное», который определяет метод 'speak()' как «Я - животное». Если вы запрашиваете их соответствующие модели, ваши данные должны быть созданы правильно. – monkut

+0

Подробнее о наследовании модели см .: https://docs.djangoproject.com/en/1.7/topics/db/models/#model-inheritance – monkut

+2

Вам нужны подклассы ... try modelutils http: // django-model-utils .readthedocs.org/ен/последний/managers.html # inheritancemanager – cdvv7788

ответ

1

У меня была эта проблема в последнее время. У меня было несколько подклассов, и у всех из них были несколько разные «говорящие» методы.

В основном я создаю функцию downcast в своем родительском классе, которая проверяет наличие соответствующих экземпляров подкласса. Это работает, потому что когда вы создаете подкласс модели, Джанго связывает их с помощью OneToOneField, который может перемещаться в обоих направлениях:

class Animal(models.Model): 
    name = models.CharField(max_length=30) 
    _downcast = None 
    # to store the subclass instance, so that 
    # subsequent calls don't hit the database 

    def speak(self): 
     return "I am an animal" 

    def downcast(self): 
     if self._downcast is None: 
      if hasattr(self, 'cat'): 
       self._downcast = self.cat 
      elif hasattr(self, 'dog'): 
       self._downcast = self.dog 

     return self._downcast 


class Cat(Animal): 
    def speak(self): 
     """ OVERRIDE """ 
     return "MEAOO" 


class Dog(Animal): 
    def speak(self): 
     """ OVERRIDE """ 
     return "WOOOOF" 

В принципе, вы просто любопытным ... пойти на это, и попросить вашу базу данных, если это Animal делает, в Дело в том, имеет связанную Cat строку:

>>> a = Animal.objects.all().first() #let's assume this is a cat 
>>> a.speak() 
I am an animal 
>>> a.downcast().speak() 
MEAOO 

конечно, это запрос к базе данных, так что производительность может принять удар. Рассмотрите свой сценарий и выполните несколько тестов, чтобы убедиться, что это сработает для вас.

Смежные вопросы