Starting in Django 1.7, migrations were built into Django and you no longer need to use south. One of the minor things that changed was the way you create data migrations. If you are familiar with South, you would create a new migration as follows:

./manage.py datamigration southtut2 hash_passwords

You had to explicitly say you were creating a data migration and provide the app it was for and a name for it. I thought this scheme was nice, because I could open up by migrations folder and differentiate between the data migrations and the automatically created migrations (based on the custom name).

Starting in Django 1.7, a data migration is created in the following manner:

./manage.py makemigrations reports --empty

In this example, reports is my django app, and I’m explicity saying I want to create data migration by passing the --empty parameter. If successful, this command should create a new file which is has a four digit number as the prefix:

013_auto_20160714_1539.py

And if you open it up, you should see the following:

# -*- coding: utf-8 -*-
# Generated by Django 1.9.2 on 2016-07-14 15:39
from __future__ import unicode_literals

from django.db import migrations


class Migration(migrations.Migration):

    dependencies = [
        ('reports', '0012_auto_update_policy_form_defaults'),
    ]

    operations = [
    ]

At this point, unfortunately I like to add an option step of renaming this file so I can can get my old south functionality back. (Note, it is important to keep the first four digits of the file name on the new filename)

mv path/to/0013_auto_20160714_1539.py path/to/0013_rename_quote_conditions.py

Now lets create a data migration. The first step is defining your forward function and updating the operations array in the migration script:

# -*- coding: utf-8 -*-
# Generated by Django 1.9.2 on 2016-07-14 15:39
from __future__ import unicode_literals

from django.db import migrations

def forward(apps, schema_editor):
    User = apps.get_model("accounts", "User")
    for user in User.objects.all():
        user.is_active = True
        user.save()

class Migration(migrations.Migration):

    dependencies = [
        ('reports', '0012_auto_update_policy_form_defaults'),
    ]

    operations = [
        migrations.RunPython(forward, migrations.RunPython.noop),
    ]

In this example, I defined a new forward function thats sole purpose is to set every user in my database to active (this is obviously a simple example, but it works.). The important thing to notice here is we are not importing django models in the top of the migration, we are using the following code to get the model:

User = apps.get_model("accounts", "User")

From the django documentation:

If you’re upgrading from South, this is basically the South pattern as an operation - one or two methods for forwards and backwards, with >an ORM and schema operations available. Most of the time, you should be able to translate the orm.Model or orm[“appname”, “Model”] >references from South directly into apps.get_model(“appname”, “Model”) references here and leave most of the rest of the code unchanged >for data migrations. However, apps will only have references to models in the current app unless migrations in other apps are added to the >migration’s dependencies.

Finally, you can execute this new data migration:

python manage.py migrate

Done!