This is the approach I've taken to access instances of child models from their parent. Functionally it's very similar to snippets [1031](http://www.djangosnippets.org/snippets/1031/) and [1034](http://www.djangosnippets.org/snippets/1034/), but without the use of `django.contrib.contenttypes`.
Usage:
class Post(ParentModel):
title = models.CharField(max_length=50)
objects = models.Manager()
children = ChildManager()
def __unicode__(self):
return self.title
def get_parent_model(self):
return Post
class Article(Post):
text = models.TextField()
class Photo(Post):
image = models.ImageField(upload_to='photos/')
class Link(Post):
url = models.URLField()
In this case, the `Post.children` manager will return a queryset containing instances of the appropriate child model, rather than instances of `Post`.
>>> Post.objects.all()
[<Post: Django>, <Post: Make a Tumblelog>, <Post: Self Portrait>]
>>> Post.children.all()
[<Link: Django>, <Article: Make a Tumblelog>, <Photo: Self Portrait>]
- model
- manager
- queryset
- inheritance
This is a different take on polymorphic inheritance, inspired by SQLAlchemy's approach to the problem.
The common Django approach (e.g. snippets 1031 & 1034, [django_polymorphic](http://github.com/bconstantin/django_polymorphic)) is to use a foreign key to `ContentType` on the parent model and override `save()` to set the right content type automatically. That works fine but it might not always be possible or desirable, for example if there is another field that determines the "real type" of an instance.
In contrast this snippet (which is actually posted and maintained at [gist.github](http://gist.github.com/608595)) allows the user to explicitly specify the field that determines the real type of an instance. The basic idea and the terminology (`polymorphic_on` field, `polymorphic_identity` value) are taken from [SQLAlchemy](http://www.sqlalchemy.org/docs/orm/inheritance.html).
Some other features:
* It works for proxy child models too, with almost no overhead compared to non-polymorphic managers (since there's no need to hit another DB table as for multi-table inheritance).
* It does not override the default (or any other) model Manager. Regular (non-polymorphic) managers and querysets are still available if desired.
* It does not require extending a custom Model base class, using a custom metaclass, monkeypatching the models or any kind of magic.