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.
5 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.

- 398,885
- 90
- 523
- 479
-
@alecxe in my migration history table exists row `applied timestamp` – coldmind Dec 11 '14 at 19:40
-
@coldmind my bad, that's correct. `applied` is not a boolean flag - it is a `datetimefield`. Thank you! – alecxe Dec 11 '14 at 19:53
-
1In my case there was already an entry in the `django_migrations` table with a row listing my app and migration (`0001 initial` in this case). Yet when I called `./manage.py migrate`, django still attempted to apply that same migration. `./manage.py migrate
--fake-initial` created another row in `django_migrations` with the same `app` and `name` fields (different `applied` and `id`, of course). Then `./manage.py migrate` finally reported no migrations to apply. This suggests the accepted answer is incomplete - why would django attempt to apply an already-listed migration? – Gabriel Oct 30 '16 at 07:00
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

- 11,582
- 18
- 69
- 119
-
2Showmigrations lists the migrations Django knows about and whether they have been applied or not. But it generates this list by looking at the django_migrations table. This table gets updated whenever you run a migration or successfully rollback a migration. – Kevin Jul 22 '19 at 22:21
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)

- 462,703
- 120
- 1,088
- 1,195
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.

- 2,597
- 2
- 29
- 22
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.

- 5,167
- 2
- 22
- 22
-
Looks like south stores migration history in table `south_migrationhistory`, though I haven't found official documentation to confirm. – CivFan Oct 05 '15 at 20:54
-
Do you know how to enable that feature to show migrations in the admin? I can't find it in the docs and am having no luck making my own. – skolsuper Nov 03 '15 at 12:09
-
@skolsuper Maybe there is a better solution, but you may describe migration model like here https://github.com/django/django/blob/4373eac99828d99718a7b245d160e7e64fce2e95/django/db/migrations/recorder.py#L26 and simply include it to admin like a usual model – coldmind Nov 03 '15 at 14:34