|Generate migrations for |
|Generate migrations for all apps|
|Resolve migration conflicts for all apps|
|Resolve migration conflicts for |
|Generate a migration for |
|Apply pending migrations of |
|Apply all pending migrations to the database|
|Apply or unapply up to |
|Unapply all migrations in |
|Prints the SQL for the named migration|
|Shows all migrations for all apps|
|Shows all migrations in |
Django uses migrations to propagate changes you make to your models to your database. Most of the time django can generate them for you.
To create a migration, run:
$ django-admin makemigrations <app_name>
This will create a migration file in the
migration submodule of
app_name. The first migration will be named
0001_initial.py, the other will start with
If you omit
<app_name> this will create migrations for all your
To propagate migrations to your database, run:
$ django-admin migrate <app_name>
To show all your migrations, run:
$ django-admin showmigrations app_name app_name [X] 0001_initial [X] 0002_auto_20160115_1027 [X] 0003_somemodel [ ] 0004_auto_20160323_1826
[X]means that the migration was propagated to your database
[ ]means that the migration was not propagated to your database. Use
django-admin migrateto propagate it
You call also revert migrations, this can be done by passing the migration name to the
migrate command. Given the above list of migrations (shown by
$ django-admin migrate app_name 0002 # Roll back to migration 0002 $ django-admin showmigrations app_name app_name [X] 0001_initial [X] 0002_auto_20160115_1027 [ ] 0003_somemodel [ ] 0004_auto_20160323_1826
Sometimes, migrations generated by Django are not sufficient. This is especially true when you want to make data migrations.
For instance, let's you have such model:
class Article(models.Model): title = models.CharField(max_length=70)
This model already have existing data and now you want to add a
class Article(models.Model): title = models.CharField(max_length=70) slug = models.SlugField(max_length=70)
You created the migrations to add the field, but now you would like to set the slug for all existing article, according to their
Of course, you could just do something like this in the terminal:
$ django-admin shell >>> from my_app.models import Article >>> from django.utils.text import slugify >>> for article in Article.objects.all(): ... article.slug = slugify(article.title) ... article.save() ... >>>
But you will have to do this in all your environments (ie. your office desktop, your laptop, ...), all your coworkers will have to do so as well, and you will have to think about it on staging and when pushing live.
To make it once and for all, we will do it in a migration. First create an empty migration:
$ django-admin makemigrations --empty app_name
This will create an empty migration file. Open it, it contains an base skeleton. Let's say your previous migration was named
0023_article_slug and this one is named
0024_auto_20160719_1734. Here is what we will write in our migration file:
# -*- coding: utf-8 -*- # Generated by Django 1.9.7 on 2016-07-19 15:34 from __future__ import unicode_literals from django.db import migrations from django.utils.text import slugify def gen_slug(apps, schema_editor): # We can't import the Article model directly as it may be a newer # version than this migration expects. We use the historical version. Article = apps.get_model('app_name', 'Article') for row in Article.objects.all(): row.slug = slugify(row.name) row.save() class Migration(migrations.Migration): dependencies = [ ('hosting', '0023_article_slug'), ] operations = [ migrations.RunPython(gen_slug, reverse_code=migrations.RunPython.noop), # We set `reverse_code` to `noop` because we cannot revert the migration # to get it back in the previous state. # If `reverse_code` is not given, the migration will not be reversible, # which is not the behaviour we expect here. ]
When a migration is run, Django stores the name of the migration in a django_migrations table.
Create and Fake initial migrations for existing schema
If your app already has models and database tables, and doesn’t have migrations. First create initial migrations for you app.
python manage.py makemigrations your_app_label
Now fake initial migrations as applied
python manage.py migrate --fake-initial
Fake all migrations in all apps
python manage.py migrate --fake
Fake single app migrations
python manage.py migrate --fake core
Fake single migration file
python manage.py migrate myapp migration_name
makemigrations --name <your_migration_name> option to allow naming the migrations(s) instead of using a generated name.
python manage.py makemigrations --name <your_migration_name> <app_name>
Sometimes migrations conflict, resulting in making the migration unsuccesful. This can happen in a lot of scenerio's, however it can occur on a regular basis when developing one app with a team.
Common migration conflicts happen while using source control, especially when the feature-per-branch method is used. For this scenario we will use a model called
Reporter with the attributes
Two developers at this point are going to develop a feature, thus they both get this initial copy of the
Reporter model. Developer A adds an
age which results in the file
0002_reporter_age.py file. Developer B adds a
bank_account field which resulsts in
0002_reporter_bank_account. Once these developers merge their code together and attempt to migrate the migrations, a migration conflict occurred.
This conflict occurs because these migrations both alter the same model,
Reporter. On top of that, the new files both start with 0002.
There are several ways of doing it. The following is in the recommended order:
The most simple fix for this is by running the makemigrations command with a --merge flag.
python manage.py makemigrations --merge <my_app>
This will create a new migration solving the previous conflict.
When this extra file is not welcome in the development environment
for personal reasons, an option is to delete the conflicting
migrations. Then, a new migration can be made using the regular
makemigrations command. When custom migrations are written, such as
migrations.RunPython, need to be accounted for using this method.
First off, let's assume this is your initial model, inside an application called
from django.db import models class Album(models.Model): name = models.CharField(max_length=255) artist = models.CharField(max_length=255)
Now, you realize that you want to use a ForeignKey for the artist instead. This is a somewhat complex process, which has to be done in several steps.
Step 1, add a new field for the ForeignKey, making sure to mark it as null (note that the model we are linking to is also now included):
from django.db import models class Album(models.Model): name = models.CharField(max_length=255) artist = models.CharField(max_length=255) artist_link = models.ForeignKey('Artist', null=True) class Artist(models.Model): name = models.CharField(max_length=255)
...and create a migration for this change.
./manage.py makemigrations discography
Step 2, populate your new field. In order to do this, you have to create an empty migration.
./manage.py makemigrations --empty --name transfer_artists discography
Once you have this empty migration, you want to add a single
RunPython operation to it in order to link your records. In this case, it could look something like this:
def link_artists(apps, schema_editor): Album = apps.get_model('discography', 'Album') Artist = apps.get_model('discography', 'Artist') for album in Album.objects.all(): artist, created = Artist.objects.get_or_create(name=album.artist) album.artist_link = artist album.save()
Now that your data is transferred to the new field, you could actually be done and leave everything as is, using the new
artist_link field for everything. Or, if you want to do a bit of cleanup, you want to create two more migrations.
For your first migration, you will want to delete your original field,
artist. For your second migration, rename the new field
This is done in multiple steps to ensure that Django recognizes the operations properly.