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:
Model A has several foreign key relationships that have to be maintained in Model B.
There should not be any primary key conflict during the migration(splitting of the model).
It took me four migrations to perform the entire change.
blank=True
id
max(id)
of the parent model to prevent any chance of collision. id
Im gonna add some code snippets specific to my project here, for giving an idea of how it was implemented.
class Migration(SchemaMigration): def forwards(self, orm): #Adding field 'B.b_name' db.add_column(u'B', 'b_name', self.gf('django.db.models.fields.CharField')(blank=True)
class Migration(SchemaMigration): def forwards(self, orm): b_objects = list(B.objects.all()) for b_object in b_objects: b_object.b_name = b_object b_object.save()
class Migration(SchemaMigration): # Changing field 'B.a_ptr_id' db.alter_column(u'B', 'a_ptr_id', self.gf('django.db.models.fields.IntegerField')(blank=True) # Renaming field 'B.a_ptr' db.rename_column(u'B', 'a_ptr_id', 'id') # Setting id as the primary key for B # with a value sequence that follows the max id on A. db.execute("CREATE SEQUENCE b_id_seq") db.execute("SELECT setval('b_id_seq', (SELECT MAX(id) FROM A))") db.execute("ALTER TABLE B ALTER COLUMN id SET DEFAULT nextval('b_id_seq'::regclass)")
class Migration(SchemaMigration): def forwards(self, orm): # Renaming field 'PartnerAccount.pa_signup_completed_at' db.rename_column(u'B', 'b_name', 'name')