So this evening I wrapped my head around what I now know as concrete inheritance. Django refers to this as multi-table inheritance. Needless to say, if you are starting with Django avoid it at all costs.

Refresher - two models like:

class Person(Model):
    name = CharField()
    ...

class Manager(Person):
    department = CharField()
    ...

Looks great on paper and reads great in the Django docs, but they really don’t explain the pitfalls of this. In my case, I’m writing a deployment tool so I have a Subnet model that stores information about subnets (obviously) for production devices, and then I have a DeploymentSubnet that inherits Subnet. So mine is more like:

class Subnet(Model):
    subnet = IpField()
    ...
 
class DeploymentSubnet(Subnet):
    deployment = ForeignKey()
    ...

First off, it has been a while since I read the model docs for Django. It’s not the clearest on how it actually works, but it creates two tables and under the hood every time you query the DeploymentSubnet it also queries the Subnet to get the rest of the fields. Grrr… Ok, I guess I don’t need that move_to_production() method on my model anymore as it’s already in the Subnet table, I just need to delete these when I’m done using them.

To delete these I can just use the DeploymentSubnet.delete(keep_parents=True) and it will keep Subnet in tact – but that does not appear to work and I am using Django 3. When attempting to delete the child, it complains about other models that are referencing Subnet. Grrr…

Needless to say this is not ideal. From the get go, just make an Abstract for everything that you need to share. It’s pretty fast and easy. This is what I ended moving to for this specific scenario:

class AbstractSubnet(Model):
    customer = ForeignKey(related_name='%(class)ss')
    vlanid = ForeignKey(related_name='%(class)ss')
    subnet = IpField()
    ...

class Subnet(AbstractSubnet):
    ...

class DeploymentSubnet(AbstractSubnet):
    deployment = ForeignKey()
    ...

Now I can go back and finish up that move_to_production() method on DeploymentSubnet. ¯\_(ツ)_/¯

Cheers.