tags:

views:

79

answers:

3

My application uses class inheritance to minimize repetition across my models. My models.py looks kind of like this:

class BaseModel(models.Model):
   title = models.CharField(max_length=100)
   pub_date = models.DateField()

class Child(BaseModel):
   foo = models.CharField(max_length=20)

class SecondChild(BaseModel):
   bar = models.CharField(max_length=20)

Now most of the time, my views and templates only deal with instances of Child or SecondChild. Once in a while, however, I have a situation where I have an instance of BaseModel, and need to figure out which class is inheriting from that instance.

Given an instance of BaseModel, let's call it base, Django's ORM offers base.child and base.secondchild. Currently, I have a method that loops through all of them to figure it out. It would look something like this:

class BaseModel(models.Model):
   ...
   def get_absolute_url(self):
      url = None
      try:
         self.child
         url = self.child.get_absolute_url()
      except Child.DoesNotExist:
         pass
      if not url:
         try:
            self.secondchild
            url = self.secondchild.get_absolute_url()
         except SecondChild.DoesNotExist:
            pass
      if not url:
         url = '/base/%i' % self.id
      return url

That is hopelessly ugly, and gets uglier with every additional child class I have. Does anybody have any ideas on a better, more pythonic way to go about this?

A: 

I haven't tested this, but it might be worth tinkering with:

def get_absolute_url(self):
    subclasses = ('child', 'secondchild', )

    for subclass in subclasses:
        if hasattr(self, subclass):
            return getattr(self, subclass).get_absolute_url()

    return '/base/%i' % self.id
sneeu
the last if isn't really needed, is it?
Marcus Lindblom
Thanks! Man, I feel so stupid.
Udbhav
A: 

I haven't messed with Django inheitance much, so I suppose you can't override get_absolute_url() in the model classes?

Perhaps the visitor pattern could help if there are lot of functions that need this in many different places.

Marcus Lindblom
I do override it, but sometimes, I have to use the the parent class, which does not have access to the get_absolute_url of it's children, until I figure what it's child actually is.
Udbhav
A: 

Various forms of this question pop up here regularly. This answer demonstrates a generic way to "cast" a parent type to its proper subtype without having to query every subtype table. That way you wouldn't need to define a monster get_absolute_url on the parent which covers all the cases, you'd just convert to the child type and call get_absolute_url normally.

Carl Meyer