Moving a Django model to another app can be tricky. Here is a quick rundown of the most convenient way I found so far. The idea is to simply rename the database tables, and force Django to consider this the new state of your models. Thanks to Marten Kenbeek who pointed me at SeparateDatabaseAndState.
This is probably still missing some edge cases and I only tested it on one project, so be careful.
- Create a backup.
- Copy the model code to the new app. Update any foreign key references as necessary.
- Run manage.py makemigrations new_app
- Edit the migration:
1 2 3 4 5 6 7 8 |
operations=[ migrations.SeparateDatabaseAndState( database_operations=None, ], state_operations=[ # Copy the auto-generated operations here. ], ), ], |
- Delete the models from the old app.
- Run manage.py makemigrations old_app
- Edit the migration:
1 2 3 4 5 6 7 8 9 10 11 |
operations = [ migrations.SeparateDatabaseAndState( database_operations=[ migrations.AlterModelTable('mymodel', 'new_app_mymodel'), # Repeat for the other models you want to move. ], state_operations=[ # Copy the auto-generated operations here. ], ), ], |
manage.py migrate
Вариант для версии 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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:
1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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) ] |
Мое решение
Удалил базу данных, удалил все миграции выполнил миграции заново и пере залил данные
Проблемы с существующими таблицами
python manage.py migrate --fake <appname>
Mark migrations as run without actually running them