Django multi-table inheritance, how to know which is the child class of a model? Django multi-table inheritance, how to know which is the child class of a model? django django

Django multi-table inheritance, how to know which is the child class of a model?


To the best of my knowledge there isn't a Django built-in way to do this.

However, given acc=account.object.get(pk=29), you can use:

try:    typeA = acc.accounttypeA    # acc is typeAexcept accounttypeA.DoesNotExist:    # acc should be typeB if account only has typeA and typeB subclassestry:    typeB = acc.accounttypeB    # acc is typeBexcept accounttypeB.DoesNotExist:    # acc should be typeA if account only has typeA and typeB subclasses


my solution was based on this

class account(models.Model):    name = models……    def cast(self):        """        This method is quite handy, it converts "self" into its correct child class. For example:        .. code-block:: python           class Fruit(models.Model):               name = models.CharField()           class Apple(Fruit):               pass           fruit = Fruit.objects.get(name='Granny Smith')           apple = fruit.cast()        :return self: A casted child class of self        """        for name in dir(self):            try:                attr = getattr(self, name)                if isinstance(attr, self.__class__) and type(attr) != type(self):                                     return attr            except:                pass    @staticmethod    def allPossibleAccountTypes():        #this returns a list of all the subclasses of account (i.e. accounttypeA, accounttypeB etc)        return [str(subClass).split('.')[-1][:-2] for subClass in account.__subclasses__()]    def accountType(self):        try:            if type(self.cast()) == NoneType:                #it is a child                return self.__class__.__name__            else:                #it is a parent, i.e. an account                return str(type(self.cast())).split('.')[-1][:-2]        except:            logger.exception()    accountType.short_description = "Account type"class accounttypeA(account):    balance = models.float…..    def addToBalance(self, value):        self.balance += valueclass accounttypeB(account):    balance = models.int…. # NOTE this


Django adds to class account two fields: accounttypea and accounttypeb. If you have accounttypeB object with pk=42, you can access from parent like this:

account.objects.get(pk=42).accounttypeb>>> <accounttypeB instance>

You can add CharField to parent model with actual child-type for every child, and then use getattr, if there are a lot of child models (it may be better than a lot of try .. except xxx.DoesNotExist blocks).

class account(models.Model):    name = models……    cls = CharField(...)      def ext(self):        return getattr(self, self.cls.lower())class accounttypeA(account):    balance = models.float…..    def addToBalance(self, value):        self.balance += valueclass accounttypeB(account):    balance = models.int…. # NOTE this    def addToBalance(self, value):        value = do_some_thing_with_value(value) # NOTE this        self.balance += value# exampleaccounttypeB.objects.create(balance=10,  name='Vincent Law', cls="accounttypeB")  accounttypeA.objects.create(balance=9.5, name='Re-l Mayer', cls="accounttypeA")  for obj in account.objects.all():    obj.ext().addToBalance(1.0)     print(obj.name, obj.cls)

but you MUST create models using accounttypeA.objects.create(...) and accounttypeB.objects.create(...) - or else this trick will not work.(https://docs.djangoproject.com/en/1.5/topics/db/models/#multi-table-inheritance)