Search code examples
pythondjangopython-2.xdjango-1.8

Inheritance: class method not accessible through use of Foreign Key


Inheritance: class method not accessible through use of Foreign Key

Hello!

Problem

I have multiples classes that inherit from the same class. There are differents relationships between instances of these classes that I need stored in another class (Relationship). To be able to link these different classes together, I use the "mother" class they all inherit from as a ForeignKey.

Everything works, except that I cannot access class methods from the subclasses when I access their instances through the Relationship table (Foreign Key).

Is there any way I could access the class method of a subclass when using the "superclass" as a Foreign Key?

Code

My code is as follows:

models.py

class SuperClass(models.Model):
    random_attribute = models.CharField()


class A(SuperClass):
    some_attribute = models.CharField()


class B(SuperClass):
    some_other_attribute = models.CharField()
    
    def class_b_method(self):
        some_code = 'goes_here'
        return some_code


class Relationship(models.Model):
    parent = models.ForeignKey(
        'app.SuperClass',
        related_name='parent',
        on_delete=models.CASCADE
    )
    child = models.ForeignKey(
        'app.SuperClass',
        related_name='child',
        on_delete=models.CASCADE
    )

views.py

def do_stuff():
    a = A('a')
    b = B('b')
    relationship = Relationship(parent=a, child=b)
    relationship.child.class_b_method()

This throws the following error:

AttributeError at xxx
'SuperClass' object has no attribute 'class_b_method'

I understand why the error is there and what it means, but I have no clue as to how to access a class B method from the Relationship table.

Any help would be appreciated, Thanks.


Solution

  • You will need to access its B model, you do this thus with:

    def do_stuff():
        a = A('a')
        b = B('b')
        relationship = Relationship(parent=a, child=b)
        
        relationship.child.b.class_b_method()

    this will thus require an extra query to obtain the related B object.

    While model inheritance is supported with a non-abstract parent. It is usually not a good idea to use this. This is modelled by extra tables with a OneToOneField to its parents. This thus means that in order to find out what subtype it is, one needs to query all possible subclasses. While that can be done efficiently to some extent, it will still result in quite "heavy" queries and a lot of bandwidth to pass subclasses to the Django/Python layer.