I’m trying to bake out a sort of “single table inheritence” a.k.a. “table per hierarchy” model in Django.
Here’s what I’d like to do:
class PolymorphicModel(models.Model):
content_type = models.ForeignKey(ContentType)
class Meta:
abstract = True
def __init__(self, *args, **kwargs):
super(PolymorphicModel, self).__init__(*args, **kwargs)
# Dynamically switch the class to the actual one
self.__class__ = self.content_type.model_class()
def save(self, *args, **kwargs):
if not self.content_type:
# Save the actual class name for the future.
self.content_type = ContentType.objects.get_for_model(self.__class__)
super(PolymorphicModel, self).save(*args, **kwargs)
And then the actual hierarchy:
class Base(PolymorphicModel):
a = models.IntegerField()
b = models.IntegerField()
@abstractmethod
def something(self): pass
class DerivedA(Base):
def something(self):
return self.a
class DerivedB(Base):
def something(self):
return self.b
Unfortunately I get an error DoesNotExist when constructing DerivedA(). It complains about content_type not existing.
EDIT:
Concerning my questions:
- Why do I get the exception, how to fix it?
See my answer below: content_type is apparently not a viable name.
- Is the thing that I’m trying to achieve doable this way?
Yes it is! And it works beautifully. Using class names instead of content type is also possible. This has an added value of handling proxy = True appropriately.
Ups, well apparently
content_typeis a reserved name. I changed the property name toctand it works now.I’ve published by solution here:
http://djangosnippets.org/snippets/2408/