South is absolutely brilliant. I never expected it to properly convert over my data as easily as it did. Basically, I originally had a monolithic table, which I wanted to convert into 3 separate tables linked together using a ForeignKey. The reason was, that 2 fields contains mostly the same information, and re-typing it, and organizing the data was becoming a tad tedious. Here is the first Python script I ran after creating the new tables. This script automatically separates the data into the required tables for me:
from tickets.models import Taxonomy, Category, Reason print "Starting Taxonomy migration process..." for tax in Taxonomy.objects.all(): print "Processing %s..." % tax try: ci = Category.objects.get(title=tax.ci) except Category.DoesNotExist: ci = Category.objects.create(title=tax.ci) print "Created Category %s." % ci try: r = Reason.objects.get(title=tax.reason) except Reason.DoesNotExist: r = Reason.objects.create(title=tax.reason) print "Created Reason %s." % r tax.ci = ci.pk tax.reason = r.pk tax.save() print "Linked PKs, finished."
As you can see, it replaces the actual category name and reason with just the PK, at first I wasn't sure what South would do with the data if I just convert a CharField over to a ForeignKey. Here are the changes to the main model:
ci = models.CharField(max_length=90, blank=True, verbose_name='CI Unique ID') reason = models.CharField(max_length=90) # To: ci = models.ForeignKey(Category, blank=True, verbose_name='CI Unique ID') reason = models.ForeignKey(Reason)
Here is the migration data generated by South:
class Migration(SchemaMigration): def forwards(self, orm): # Renaming column for 'Taxonomy.ci' to match new field type. db.rename_column('tickets_taxonomy', 'ci', 'ci_id') # Changing field 'Taxonomy.ci' db.alter_column('tickets_taxonomy', 'ci_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['tickets.Category'])) # Adding index on 'Taxonomy', fields ['ci'] db.create_index('tickets_taxonomy', ['ci_id']) # Renaming column for 'Taxonomy.reason' to match new field type. db.rename_column('tickets_taxonomy', 'reason', 'reason_id') # Changing field 'Taxonomy.reason' db.alter_column('tickets_taxonomy', 'reason_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['tickets.Reason'], max_length=90)) # Adding index on 'Taxonomy', fields ['reason'] db.create_index('tickets_taxonomy', ['reason_id'])
All in all, there was almost no work required, besides writing up a quick Python script to move the actual data to a new table, and place the PK into it. According to the database, the fields are now INTs, as they should be for ForeignKeys.