Using South for schema and data migrations in Django
South is a schema and data migrations for Django. In an easy way you may update your database tables after you change your models. It also keeps all migrations in the codebase allowing to migrate backward if needed. In this article I'll show some standard South usage cases.
Installing and configuring South
The quickest way to install south is to use pipLBasic usage
Without south you would use syncdb to create table of your new models. When using south you create migrations to do all the database work, including the initial migration creating tables:from django.db import models
class MyModel(models.Model):
name = models.CharField(max_length=100)
class MyModel(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(blank=True)
In this example south will do everything on its own and we can just execute the migration.
Now lets try a field that can't be empty:
class MyModel(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(blank=True)
number = models.IntegerField()
? The field 'MyModel.number' does not have a default specified, yet is NOT NULL. ? Since you are adding this field, you MUST specify a default ? value to use for existing rows. Would you like to: ? 1. Quit now, and add a default to the field in models.py ? 2. Specify a one-off value to use for existing columns now
You can choose 1 and quit (and then for example add default to the field) or use 2 and provide a default value for the migration (value used only for entries existing at the time of migration).
Data migrations
What if we would want to add a unique field to a table with existing entries?:slug = models.SlugField(unique=True)
slug = models.SlugField(unique=True, null=True)
The plan is simple - we create such column (migration), then we do a data migration (we make unique values for the existing entries) and in the end we remove the null with another schema migration.
To make an empty data migration use this:# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
class Migration(DataMigration):
def forwards(self, orm):
# Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..."
def backwards(self, orm):
"Write your backwards methods here."
The forwards method is used to make the migration. backwards is used to do a backward migration (if it's something complex/non reversible you can disable it). The key element is to write the migration.
Here is a simple example providing unique values for the slug column (we could use Django slugify helper and some unique value generators, but this is just an example): def forwards(self, orm):
# Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..."
for i in orm['first_app.MyModel'].objects.all():
i.slug = i.id
i.save()
Backward migrations
South allows backward migrations. You can migrate to an older migration by specifying its number:Dependencies for migrations
In some cases when you have migrations covering model/database relations there may be a problem with the order in which migrations are executed. The migration with the relation may try to execute before the related table will be created by another migration. To apply correct order we can use "depends_on" in the migration class:
depends_on = (
("APPLICATION_NAME", "NAZWA_MIGRACJI"),
)
Such problems may show up during tests or build processes where everything is created from scratch.
You will find more in the south documentation.
Comment article