View on GitHub

Ann Molly Paul

learn -- code -- inspire

Separating inherited models in Django using South migrations

December 23, 2014

The way models are inherited in Django is such that the inherited model maintains a pointer to the parent model using the parent's primary key to maintain foreign key relationships. It also doesnt duplicate the fields in the inherited model. This makes it difficult when you want to losslessly separate out models so that they retain all it's attributes and relationships to other models in an efficient, non-blocking way.

Consider you have 2 models of the following form:

    class A(models.Model):
        name = models.CharField()
    class B(A):
        number = models.IntergerField()

Some things to keep in mind are:

It took me four migrations to perform the entire change.

  1. Duplicate the attributes with a temporary name in the child model.
  2. Since the child objects still have a pointer to the parent model, we duplicate the values for every instance, into the temporary fields that were added onto the model.
    • Alter and set the ptr foreign key to the parent model to a regular Interger Field withblank=True
    • Rename the ptr field to id
    • Now to create a sequence for the id for the objects that get created after the migration. The sequence should start from the max(id) of the parent model to prevent any chance of collision.
    • Finally assign the created sequence as the default nextval for the column id
  3. Since there is no pointer to the parent table, there no longer are any of the parent model fields on Model B. So, we can now rename the temporary fields to that of the parent model.
  4. Now that the models are separated, all the objects of Model A with an id equal to that of Model B, can be safely deleted. This deletes the objects that earlier held the data of Model B and is now completely separated out.

Im gonna add some code snippets specific to my project here, for giving an idea of how it was implemented.