How to move a model between two Django apps (Django 1.7) How to move a model between two Django apps (Django 1.7) python python

How to move a model between two Django apps (Django 1.7)


This can be done fairly easily using migrations.SeparateDatabaseAndState. Basically, we use a database operation to rename the table concurrently with two state operations to remove the model from one app's history and create it in another's.

Remove from old app

python manage.py makemigrations old_app --empty

In the migration:

class Migration(migrations.Migration):    dependencies = []    database_operations = [        migrations.AlterModelTable('TheModel', 'newapp_themodel')    ]    state_operations = [        migrations.DeleteModel('TheModel')    ]    operations = [        migrations.SeparateDatabaseAndState(            database_operations=database_operations,            state_operations=state_operations)    ]

Add to new app

First, copy the model to the new app's model.py, then:

python manage.py makemigrations new_app

This will generate a migration with a naive CreateModel operation as the sole operation. Wrap that in a SeparateDatabaseAndState operation such that we don't try to recreate the table. Also include the prior migration as a dependency:

class Migration(migrations.Migration):    dependencies = [        ('old_app', 'above_migration')    ]    state_operations = [        migrations.CreateModel(            name='TheModel',            fields=[                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),            ],            options={                'db_table': 'newapp_themodel',            },            bases=(models.Model,),        )    ]    operations = [        migrations.SeparateDatabaseAndState(state_operations=state_operations)    ]


I encountered the same problem.Ozan's answer helped me a lot but unfortunately was not enough. Indeed I had several ForeignKey linking to the model I wanted to move. After some headache I found the solution so decided to post it to solve people time.

You need 2 more steps:

  1. Before doing anything, change all your ForeignKey linking to TheModel into Integerfield. Then run python manage.py makemigrations
  2. After doing Ozan's steps, re-convert your foreign keys: put back ForeignKey(TheModel)instead of IntegerField(). Then make the migrations again (python manage.py makemigrations). You can then migrate and it should work (python manage.py migrate)

Hope it helps. Of course test it in local before trying in production to avoid bad suprises :)


I am removing the old answer as may result in data loss. As ozan mentioned, we can create 2 migrations one in each app. The comments below this post refer to my old answer.

First migration to remove model from 1st app.

$ python manage.py makemigrations old_app --empty

Edit migration file to include these operations.

class Migration(migrations.Migration):    database_operations = [migrations.AlterModelTable('TheModel', 'newapp_themodel')]    state_operations = [migrations.DeleteModel('TheModel')]    operations = [      migrations.SeparateDatabaseAndState(        database_operations=database_operations,        state_operations=state_operations)    ]

Second migration which depends on first migration and create the new table in 2nd app. After moving model code to 2nd app

$ python manage.py makemigrations new_app 

and edit migration file to something like this.

class Migration(migrations.Migration):    dependencies = [        ('old_app', 'above_migration')    ]    state_operations = [        migrations.CreateModel(            name='TheModel',            fields=[                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),            ],            options={                'db_table': 'newapp_themodel',            },            bases=(models.Model,),        )    ]    operations = [        migrations.SeparateDatabaseAndState(state_operations=state_operations)    ]