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.
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).
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()
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.