0

I'm looking for a way to get a list of all classes that derive from a particular base class in Python.

More specifically I am using Django and I have a abstract base Model and then several Models that derive from that base class...

class Asset(models.Model):
    name = models.CharField(max_length=500)
    last_update = models.DateTimeField(default=datetime.datetime.now())
    category = models.CharField(max_length=200, default='None')

    class Meta:
        abstract = True

class AssetTypeA(Asset):
    junk = models.CharField(max_length=200)
    hasJunk =  models.BooleanField()

    def __unicode__(self):
        return self.junk

class AssetTypeB(Asset):
    stuff= models.CharField(max_length=200)

    def __unicode__(self):
        return self.stuff

I'd like to be able to detect if anyone adds a new AssetTypeX model and generate the appropriate pages but currently I am maintaining a list manually, is there a way to determine a list of class names for anything that derives from "Asset"?

Fraser Graham
  • 4,650
  • 4
  • 22
  • 42
  • Hadn't thought of that, but I'd need to know what files to grep in, not all the models are in the same file and I don't want to grep the whole source tree. – Fraser Graham Dec 31 '09 at 17:49
  • 1
    You can teach a parent class to keep track of its children as they're declared by making use of a custom metaclass, but it's really a lot of work for something that frankly sounds a little bit trivial. – Azeem.Butt Dec 31 '09 at 17:50
  • Duplicate of http://stackoverflow.com/questions/44352/iterate-over-subclasses-of-a-given-class-in-a-given-module – quamrana Dec 31 '09 at 18:24

1 Answers1

9

Asset.__subclasses__() gives the immediate subclasses of Asset, but whether that's sufficient depends on whether that immediate part is a problem for you -- if you want all descendants to whatever number of levels, you'll need recursive expansion, e.g.:

def descendants(aclass):
  directones = aclass.__subclasses__()
  if not directones: return
  for c in directones:
    yield c
    for x in descendants(c): yield x

Your examples suggest you only care about classes directly subclassing Asset, in which case you might not need this extra level of expansion.

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395