Search code examples
pythondjangoinheritancesubclasspermalinks

Django Inheritance and Permalinks


I'm creating a simple CMS in django, with multiple "modules" (each as a django app). I've set up the following models:

class FooObject(models.Model):
    id = models.SlugField(primary_key=True)
    name = models.CharField(max_length=255)
    creator = models.ForeignKey(auth.models.User, editable=False, related_name="createdby")

class FooPage(FooObject):
    content = models.TextField(blank=True, null=True)

    @models.permalink
    def get_absolute_url(self):
        return ('page', (), {'page_id':self.id}

class FooSubitem(FooObject):
    parent = models.ForeignKey(FooPage, related_name='subitems')

In each of the modules, I create a subclass of FooPage, and at least one subclass of FooSubitem, e.g.

# in FooBlog.models
class FooBlog(FooPage):
    owner = models.ForeignKey(auth.models.User, editable=False)

    @models.permalink
    def get_absolute_url(self):
        return ('blog', (), {'blog_id':self.id})

class FooPost(FooSubitem):
    post_time = models.DateTimeField(auto_now_add=True)

and

# in FooGallery.models
class FooGallery(FooPage):
    location = models.CharField(max_length=255)

    @models.permalink
    def get_absolute_url(self):
        return ('gallery', (), {'gallery_id':self.id})

class FooImage(FooSubitem):
    image_file = models.ImageField(upload_to='foogallery')

These are simplifications, but should give you a good idea of what I'm trying to do. In the admins for FooPost and FooImage, I restrict the parent selection list to their corresponding parent pages.

My problem arises when I try to use these in a template. In each view, I have the following:

page_list = FooPage.objects.all()

which returns a list of all FooPages, of both FooBlog and FooGallery types. However, when I iterate through this list:

{% for page in page_list %}{{ page.get_absolute_url }}{% endfor %}

it returns the 'page' url pattern, not the 'blog' or 'gallery' url pattern.

How do I make this work without having to rewrite the code when I want to add a FooCalendar module later on? I want to make sure this works with any possible module.

Thanks,

  • Lexo

Solution

  • The classic solution to this problem tends to be adding a ContentType to the superclass which stores the type of subclass for that instance. This way you can rely on a consistent API that returns the related subclass object of the appropriate type.