5. Migrations

Robert Crowther Feb 2022
Last Modified: Feb 2023

PrevNext

Migrations means changing the database structuring computer code to automate. This is easier than changing database structure by hand, much easier. Originally, I think Django had no migration code, especially, avoid older web posts about ‘South’. Migration is a subject that comes up whenever apps are created or changed, so has it’s own section.

Not to be confused with ‘migranes’.

Migration overview

Migrations in Django are a two step process. First, you ‘makemigrations’. This creates the descriptions of the database changes in the folders labelled ‘migrations’. One advantage of this hesitant step is that, since the ‘migrations’ are live Python code, you can edit them. There’s no need for editing until you get deeply into Django maintenance, though. Run this—and there is no harm in running it, if there is nothing to do, then the code will tell you,

./nanage.py makemigrations [optionally, an appname]

Migrate one app only,

./nanage.py migrate review

Handling Migrations

Django has never had a consistent approach. If you do a lot of this there are apps to help e.g. django‐extensions has some migration and model helpers.

This is a useful command,

./manage.py showmigrations [appname]

Show all migrations.

Rollback by steps

If you’ve not migrated, but run ‘makemigrations’, go in the ‘migrations/’ directory and delete the latest migration code.

If you have migrated, enter whatever number migration you need (look at the folder),

./manage.py migrate 0003

do your adjustments, re‐migrate,

./manage.py migrate 0004

Zero

Rollback all migrations,

./manage.py migrate review zero

This, I recall, will remove the DB table entirely.

Zero (compact all migrations in) an app

Compact all migrations into one. First, reset the migration records in the database. However, use –fake so the migrations are not run,

./manage.py migrate --fake review zero

Then remove all migration files inside the app directory ‘myApp/migrations’. Do not delete __init__.py. Now make the migration from zero. Then pretend you are doing the first migration (not doing it, ask Django to register it has run the migration, because the table exists)

./manage.py makemigrations review
./manage.py migrate --fake-initial review

In the early days of Django, life was worse.

Remove an app

Removing a Django app is not easy,

  1. Remove references to, or from, the app in other apps

  2. Zero migrations (the Database stores records, so deletion of the files is not enough)

  3. Clean database

  4. Remove references from siteName/urls.py and siteName/settings.py

  5. Delete the app folder itself

I’ve not tried this, but you may like to try this first. Empty the models.py file in the app, then,

./manage.py makemigrations review
./manage.py migrate review

Does it delete the DB table? Someone is doing this.

Another way: remove references to the app, as far as you can. References in import statements, models, urls etc. But leave the app registered in settings.py. Then zero the migrations,

./manage.py migrate review zero

In SQLite this drops the table too. I don’t remember for other databases.You may need to remove model tables, maybe with,

./manage.py dbshell

then,

DROP reviews_review;

Note that the table name joins the app name to the model name.

Now remove references to the app, in settings.py. If you’ve got that far, you can copy out anything you wish to keep, then delete the directory.

To do this job fully, you could read a guide to deleting Django apps, or check the web for the tricks others use.

Drop DB but keep migrations

Personally, I find the reverse, maintaining data but clearing migrations, is more common and useful. Anyway, this action is easy. Be afraid,

./manage.py flush

Drop entire database

Note this is a ‘reset to initial state’, It kills all Django management material too, like superuser logon details. Unnervingly, it is easier than deleting an app, especially if the site database is SQLite.

First, delete the contents of /migrations directories inside all Django applications. Do not delete the directories themselves, or __init__.py. Then delete or backup‐by‐rename the db.sqlite3 file (don’t worry, it will reappear). Now you are back to square one. For data, anyhow. You do have all the apps and code in place.

Hint, to get going again,

# make Django tables
./manage.py migrate

# make superuser
./manage.py createsuperuser

# complete migration of existing systems
./manage.py makemigrations
./manage.py migrate

DB notes

Ignore any mention of ‘syncdb’, it’s deprecated. But you may find useful,

./manage.py inspectdb [table [table ...]]

Refs

Django documentation on migrations,

https://docs.djangoproject.com/en/4.0/topics/migrations/