How does django know which migrations have been run?

Question:

How does django know whether a migration has been applied yet? It usually gets it right, but when it doesn’t I don’t ever know where to start troubleshooting.

Asked By: BostonJohn

||

Answers:

Django writes a record into the table django_migrations consisting of some information like the app the migration belongs to, the name of the migration, and the date it was applied.

Answered By: mipadi

If it is django1.7, it stores history to database, table django_migrations.
South also stores migrations in database, and you can enable feature to show migration history in django admin.

Answered By: coldmind

As other answers state, django has a special table django_migrations where it keeps the migration history.

If you are interested in digging a lit bit more, see MigrationRecorder class that is responsible for recording migrations in the database. Also, here is the underlying model for django_migrations table:

class Migration(models.Model):
    app = models.CharField(max_length=255)
    name = models.CharField(max_length=255)
    applied = models.DateTimeField(default=now)

    class Meta:
        apps = Apps()
        app_label = "migrations"
        db_table = "django_migrations"

    def __str__(self):
        return "Migration %s for %s" % (self.name, self.app)
Answered By: alecxe

You can simply use showmigrations command to provide a list of migrations

$ python manage.py showmigrations

whether or not each migration is applied (marked by an [X] next to the migration name).

~/workspace $ python manage.py showmigrations
admin
 [X] 0001_initial
 [X] 0002_logentry_remove_auto_add
auth
 [X] 0001_initial
 [X] 0002_alter_permission_name_max_length
 [X] 0003_alter_user_email_max_length
 [X] 0004_alter_user_username_opts
 [X] 0005_alter_user_last_login_null
 [X] 0006_require_contenttypes_0002
 [X] 0007_alter_validators_add_error_messages
contenttypes
 [X] 0001_initial
 [X] 0002_remove_content_type_name
sessions
 [X] 0001_initial
Answered By: Deano

Using showmigrations is great for the basic use case. Hopefully you never have to use anything beyond that. However, if you start using the “replaces” functionality to squash migrations, the expected behavior can become extremely non-trivial.

As a part of the answer to the question “how does Django know what migrations have been run?”, they store records of applied migrations in the database!

If you want to have a peek at what they store in the database, take a gander at the following using the Django shell.

from django.db.migrations.recorder import MigrationRecorder
[(m.app, m.name) for m in MigrationRecorder.Migration.objects.all()]

For simple cases, this should directly correspond 1-to-1 with what you are showed with showmigrations. However, squashed some migrations (replaced some migrations with others), you should know that Django compares the migrations stored in the database to the migrations stored on disk, and the process becomes quite non-trivial.

So to refine this answer to “how does Django know which migrations have been run?” The command showmigrations shows the result of Django’s migration resolution algorithm, which uses several sources of information, one of which includes a table with the names of all the literal names of the migrations that have been applied. For how you go from one to the other… read the source code.

Answered By: AlanSE