[django] How to revert the last migration?

This answer is for similar cases if the top answer by Alasdair does not help. (E.g. if the unwanted migration is created soon again with every new migration or if it is in a bigger migration that can not be reverted or the table has been removed manually.)

...delete the migration, without creating a new migration?

TL;DR: You can delete a few last reverted (confused) migrations and make a new one after fixing models. You can also use other methods to configure it to not create a table by migrate command. The last migration must be created so that it match the current models.


Cases why anyone do not want to create a table for a Model that must exist:

A) No such table should exist in no database on no machine and no conditions

  • When: It is a base model created only for model inheritance of other model.
  • Solution: Set class Meta: abstract = True

B) The table is created rarely, by something else or manually in a special way.

  • Solution: Use class Meta: managed = False
    The migration is created, but never used, only in tests. Migration file is important, otherwise database tests can't run, starting from reproducible initial state.

C) The table is used only on some machine (e.g. in development).

  • Solution: Move the model to a new application that is added to INSTALLED_APPS only under special conditions or use a conditional class Meta: managed = some_switch.

D) The project uses multiple databases in settings.DATABASES

  • Solution: Write a Database router with method allow_migrate in order to differentiate the databases where the table should be created and where not.

The migration is created in all cases A), B), C), D) with Django 1.9+ (and only in cases B, C, D with Django 1.8), but applied to the database only in appropriate cases or maybe never if required so. Migrations have been necessary for running tests since Django 1.8. The complete relevant current state is recorded by migrations even for models with managed=False in Django 1.9+ to be possible to create a ForeignKey between managed/unmanaged models or to can make the model managed=True later. (This question has been written at the time of Django 1.8. Everything here should be valid for versions between 1.8 to the current 2.2.)

If the last migration is (are) not easily revertible then it is possible to cautiously (after database backup) do a fake revert ./manage.py migrate --fake my_app 0010_previous_migration, delete the table manually.

If necessary, create a fixed migration from the fixed model and apply it without changing the database structure ./manage.py migrate --fake my_app 0011_fixed_migration.