# just a demo example # the actual code is at http://gist.github.com/608595 from django.db import models from polymorphic import polymorphic_manager class Player(models.Model): hitpoints = models.PositiveIntegerField(default=100) # polymorphic_on field race = models.SmallIntegerField(choices=enumerate(['Elf', 'Troll', 'Human'])) # keep the default (non-polymorphic) manager objects = models.Manager() # a new manager polymorphic on Player.race objects_by_race = polymorphic_manager(on=race) def __unicode__(self): return u'Player(%s)' % self.pk class Elf(Player): bows = models.PositiveIntegerField(default=0) # polymorphic manager for race=0 objects = Player.objects_by_race.polymorphic_identity(0) def __unicode__(self): return u'Elf(%s)' % self.pk class Troll(Player): axes = models.PositiveIntegerField(default=0) # polymorphic manager for race=1 objects = Player.objects_by_race.polymorphic_identity(1) def __unicode__(self): return u'Troll(%s)' % self.pk class Human(Player): # polymorphic manager for race=2 objects = Player.objects_by_race.polymorphic_identity(2) class Meta: proxy = True def __unicode__(self): return u'Human(%s)' % self.pk def test(): from random import choice Player.objects.all().delete() # create a bunch of random type players for i in xrange(10): choice([Elf, Troll, Human]).objects.create() # retrieval through the polymorphic manager returns instances of the right class print "Automatically downcast players:", Player.objects_by_race.all() # retrieval through default Player manager returns Player instances as usual players = Player.objects.all() print "Non-downcast players:", players # but they can be explicitly downcast to the right class print "Explicitly downcast players:", map(Player.objects_by_race.downcast, players) # retrieving the instances of a specific class works as expected print "Elfs:", Elf.objects.all() print "Trolls:", Troll.objects.all() print "Humans:", Human.objects.all() test()