Month: December 2014

Django: South Migrations made easy!

Hi, everyone! This is a basic tutorial on South Migrations as explained by my mentor Mr Sayan Chaudhury.

What are Migrations and why do we need them?

Migrations are Django’s way of propagating changes to your existing database schema (adding new fields or modifying/deleting existing fields in an database model).We all know that syncdb effectively creates database tables from the models.py file in your django app folder. But as your app evolves with time, you may need to add many new fields to your existing database models and syncdb cannot alter existing database tables! This is one major limitation of syncdb and hence we don’t generally use it more than once while developing a django app.South is a Django project which provides easy to use, consistent and effective database-agnostic migrations which solves this problem.

How does South Migrations work?

Firstly to install South, do the following steps:

  1. pip install south
  2. add ‘south’ to your project’s INSTALLED_APPS
  3. run ‘syncdb’ (before you create your own models).Note that the work of syncdb is done here and we are not going to use it again!
  4. run ‘manage.py migrate‘ to migrate the changes.

Now lets create a new app in our project.

./manage.py startapp south_app

Add this app as well to your project’s INSTALLED_APPS and open south_app/models.py


from django.db import models
class UserProfile(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)


Now you need to migrate these changes.This involves two steps. We need to do a schemamigration followed by a migrate. There are several ways of creating migrations, some are automatic and some are manual. The two basic automatic ways are –auto and –initial. When we doing a schemamigration for the first time, we need to use –initial. This will create the database table for us. Note that once the schemamigration has already been done once, we use –auto instead of –initial. Run the following command to migrate the changes.

./manage.py schemamigration south_app –inital

This command creates a 0001_initial.py file in the south_app/migrations/

This file consist of a class Migration consisting of two fnctions namely forwards function and backwards function. The forwards function creates a database table UserProfile and the backwards function deletes the database table UserProfile. At the bottom of the file you will also find the modified database schema of the app.


coder@coder:~/test/south_test$ ./manage.py schemamigration south_app –initial
Creating migrations directory at ‘/home/coder/test/south_test/south_app/migrations’…
Creating __init__.py in ‘/home/coder/test/south_test/south_app/migrations’…
+ Added model south_app.UserProfile
Created 0001_initial.py. You can now apply this migration with: ./manage.py migrate south_app


Run ./manage.py migrate south_app to  apply the migrate.                                  This command will run 0001_initial.py file which will create the database table UserProfile and add an entry to the SouthMigrationHistory table. The SouthMigrationHistory table keeps a record of all the migrations that have been done so far and have filename, appname and timestamp as its attributes.


coder@coder:~/test/south_test$ ./manage.py migrate south_app
Running migrations for south_app:
– Migrating forwards to 0001_initial.
> south_app:0001_initial
– Loading initial data for south_app.
Installed 0 object(s) from 0 fixture(s)


You can now add entries to the UserProfile table from the shell.

Now we will try adding new fields to UserProfile and modifying the existing fields.


from django.db import models
class UserProfile(models.Model):
first_name = models.CharField(max_length=100, unique=True)
last_name = models.CharField(max_length=100)
is_student = models.BooleanField()


We have set the first_name to be unique and added boolean field is_student.

Run ./manage.py schemamigration UserProfile –auto  for migrating the above changes.

Note that we have replace –auto by –initial since this time we have modified an existing model and did not create a new one.


coder@coder:~/test/south_test$ ./manage.py schemamigration south_app –auto
+ Added field is_student on south_app.UserProfile
+ Added unique constraint for [‘first_name’] on south_app.UserProfile
Created 0002_auto__add_field_userprofile_is_student__add_unique_userprofile_first_n.py. You can now apply this migration with: ./manage.py migrate south_app


Notice that a new file 0002_auto__add_field_userprofile_is_student__add_unique_userprofile_first_n.py.  has been created in the south_app/migrations directory. The forwards function in this file is for adding is_student field and adding a new unique constraint to first_name and the backwards function is for deleting  is_student field and removing the unique constraint on field first_name.

Now run ./manage.py migrate south_app to apply this migrate. This will create a new entry in the SouthMigrationHistory table and run 0002_auto__add_field_userprofile_is_student__add_unique_userprofile_first_n.py.  which will make the required changes in the database table UserProfile.

Few more things you need to know about South Migration…

  • If we make a few modifications to a model and migrate the changes and then realize that these modifications need refinement, in that case we can use –update.Consider the following UserProfile model.

from django.db import models
class UserProfile(models.Model):
first_name = models.CharField(max_length=100, unique=True)
last__name = models.CharField(max_length=100)
is_student = models.CharField(max_length=100)


Consider that we have already run the schemamigration and migrate commands and now we need the last__name to last_name and is_student should be a boolean field instead of a char field.

In this case, we can make the required changes in the model and run the following commands.

./manage.py schemamigration south_app –auto–update            


coder@coder:~/test/south_test$ ./manage.py schemamigration south_app –auto –update
+ Added field is_student on south_app.UserProfile
+ Added unique constraint for [‘first_name’] on south_app.UserProfile
Migration to be updated, 0002_auto__add_field_userprofile_is_student__add_unique_userprofile_first_n, is already applied, rolling it back now…
previous_migration: 0001_initial (applied: 2014-12-26 06:56:32.214512+00:00)
Running migrations for south_app:
– Migrating backwards to just after 0001_initial.
< south_app:0002_auto__add_field_userprofile_is_student__add_unique_userprofile_first_n
Updated 0002_auto__add_field_userprofile_is_student__add_unique_userprofile_first_n.py. You can now apply this migration with: ./manage.py migrate south_app


South will remove the most recent migration which created the model but included the mistakes and replace it with a new migration that corrects the mistake. It will use the backwards function to remove the previous migration.

We can now run ./manage.py migrate south_app to apply the migrate.

  • South also automatically detects ManyToMany fields; when you add the field, South will create the table the ManyToMany represents, and when you remove the field, the table will be deleted.
  • Sometimes it may so happen that we add dumps as test data which can result in an error that a particular field is not found. This occurs since the SouthMigrationHistory table has an entry which shows that the field has been added but the field does not exist in the database table. This issue can be solved by first commenting that particular field in the models.py file and running schemamigration followed by a migrate command with –fake . This will create an entry in the SouthMigrationHistory table that the field has been deleted without actually removing the field from the database table (ie- since the field doesn’t actually exist in the database table). Now uncomment the field in the models.py file and do a schemamigration  followed by a migrate without fake.This will add an new entry in the SouthMigrationHistory table that a new field has been created and it will also add this field to the database table.

Note that if we have done a list of schemamigrations without a migrate, when we do a migrate for the first time it will run the files created in the migrations folder sequentially in the order in which they were created.

  • Lastly, inorder to list the migrations that we have applied so far run the following command.

./manage.py migrate –list

We would get the following list of migrations that we have applied.


south_app
(*) 0001_initial
( ) 0002_auto__add_field_userprofile_is_student__add_unique_userprofile_first_n