How to do a migration that removes an app

I have an existing database with two apps, which have ended up being relatively similar (in that they hold data about external organisations, and their role for our users). Having two separate tables with similar data is not great.

I want to migrate all of this to a single app - so all this data is stored in a single table, with markers to say what role they hold, and then history tables which will track communications with these organisations etc.

I have a working migration script - but the migration fails if i remove either of the two specific apps from the settings - installed apps list.

How can i do the migration cleanly while also removing the old apps from the settings file.

I have done this multiple times but I’m not 100% sure I remember all the necessary steps.

What I would do:

  • Remove almost all code from the app’s files, leave an empty models.py file around
  • For this, you also have to remove references from other apps to the app to be removed
  • Run manage.py makemigrations, this should produce migrations which remove all of the app’s tables from the database
  • For the above two steps, the app still has to be in INSTALLED_APPS otherwise migrations aren’t created and applied.

The problem is that you now may still have migrations from other apps depending on models in the app you are about to remove. Editing migrations by hand can lead to breakage and data loss, so you should really take care here. You may be able to squash migrations from other apps together so that the removed app isn’t referenced in any active migrations dependencies anymore.

That’s the steps which are recommended here as well: How to delete a Django application | Django documentation | Django

Alternatively, you might be able to recreate all migrations from scratch and apply them using manage.py migrate --fake-initial. This could have other benefits such as faster test runs. But, as I said, the potential for code and database to get out of sync is real, and this will hurt a lot, probably immediately and certainly later.

You should certainly verify that you have a backup which you can restore first and only then attempt any of these steps.

I have removed Apps before - that isn’t an issue.

But I have a migration defined for the new app which includes copying data from the old apps models, which therefore needs the old apps to still exists so that the ORM can find the data.

The only options seems to be - 1) copy the old apps models but mark them as unmanaged, so at least the ORM can access the data, or only remove the old apps in a release after the new app is released.
Neither seems ideal.

You can’t do everything in one step. You have to migrate the data, and only then you can remove the app. But then it will (or might) be possible, to remove it altogether.