Login

Model inheritance with content type

Author:
crucialfelix
Posted:
September 7, 2008
Language:
Python
Version:
1.0
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. Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months 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.