Polymorphic inheritance ala SQLAlchemy

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# 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()

More like this

  1. Custom Django manager that excludes subclasses by sciyoshi 5 years, 8 months ago
  2. Ordered items in the database - alternative by Leonidas 6 years, 10 months ago
  3. Ordered items in the database by Leonidas 6 years, 11 months ago
  4. models.py with django_dag models for parts hierarchy by j_syk 2 years, 8 months ago
  5. Complex Formsets by smagala 5 years, 3 months ago

Comments

(Forgotten your password?)