Login

Model inheritance with content type

Author:
crucialfelix
Posted:
September 7, 2008
Language:
Python
Version:
1.0
Tags:
inheritance
Score:
4 (after 4 ratings)

Contact is a parent class. Subclasses might be Company, Person, Artist, Label etc. Basic address, email etc. fields can be added to the parent class and all subclasses will have those.

Having searched your database for contacts (undifferentiated by class) you then want to reload the chosen object as the subclass that it really is :

thing.as_leaf_class

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
from django.contrib.contenttypes.models import ContentType

class Contact(models.Model):

    content_type = models.ForeignKey(ContentType,editable=False,null=True)

    def save(self):
        if(not self.content_type):
            self.content_type = ContentType.objects.get_for_model(self.__class__)
        self.save_base()

    def as_leaf_class(self):
        content_type = self.content_type
        model = content_type.model_class()
        if(model == Contact):
            return self
        return model.objects.get(id=self.id)

More like this

  1. Model inheritance with content type and inheritance-aware manager by dan90 6 years, 6 months ago
  2. convenience parent class for UserProfile model by willhardy 5 years, 11 months ago
  3. Limit queryset to objects related to parent in ManyToMany fields within admin inlines by DrMeers 4 years, 10 months ago
  4. Custom Django manager that excludes subclasses by sciyoshi 6 years, 7 months ago
  5. Easier and Faster than flatpages. Rendering templates by simpling calling by his path on the URL by mariocesar 3 years ago

Comments

tygielzchaosem (on January 30, 2009):

One may achieve a similar goal without using ContentType. I suppose this boosts performance by omitting one DB hit if used with select_related():

class Base(models.Model):
    classname = models.CharField(max_length=32, editable=False, null=True)

    def save(self):
        self.classname = self.__class__.__name__
        self.save_base()

    def get_concrete(self):
        return self.__getattribute__(self.classname.lower())

This solution is, though, limited to only one inheritance level, but it could be extended by adding further get_concrete() to child classes.

#

vdboor (on May 19, 2013):

For a sophisticated solution, consider looking at django-polymorphic too!

#

Please login first before commenting.