0

My models are organized as follows.

class Animal(models.Model):

  first_name = models.CharField(max_length=128, unique=True)

class Cat(Animal):

  def make_sound(self):
    return "mreooooow"

class Dog(Animal):

  def make_sound(self):
    return "AARF!"

class EvilMonkey(Animal):

  def make_sound(self):
    return "muahahaha ..."

As you see, the various animals inherit from a class called 'Animal.' Each subclass also has a method make_sound.

However, in my view, when I call make_sound on a generic animal, Django complains that Animal objects have no method called make_sound, which makes sense since only objects of subclasses of Animal have the method.

Can I somehow tell Django that I can guarantee that all objects of subclasses of Animal have the make_sound method? Via something like a Java interface? I know that Django documentation said that "Field name "hiding" is not permitted," but I feel that overriding methods so fundamental to inheritance that Django should support it.

I don't want to have to be specific and call say my_animal.cat.make_sound() since I want to treat the animal objects generically.

dangerChihuahua007
  • 19,401
  • 30
  • 112
  • 205

2 Answers2

1

This article provides some insight. It would be convenient if there was an easier way. The "more efficient technique" looks promising.

Community
  • 1
  • 1
Nathaniel
  • 691
  • 4
  • 14
  • Thanks! That article did it! Now, I can call `make_sound` on generic animals. I can't get the more efficient way to work for some reason ... – dangerChihuahua007 Jan 21 '13 at 22:16
1

The trouble isn't that Animal doesn't know about make_sound. It's simply that when you ask for an Animal in Django, that's what you get: even if that Animal is "actually" a subclass rather than the base class, only the base instance will be returned. That's because Django doesn't attempt to do the query to find if there's a related item in any of the subclassed tables - which is probably on balance a good thing, since you would have many many unnecessary queries.

The only thing to do is to record what type of Animal it is on the base class, then write a method to get the relevant subclass from that.

Daniel Roseman
  • 567,968
  • 59
  • 825
  • 842