You have a legacy database in your django application, but created models for it. At first, they were unmanaged, but then you realized that it’d be easier for everyone if django handled the whole database. Now you’re left with a bunch of fields having db_column set and are required to change the field name and also the column name in the database.
Example model looks like this:
class Person(models.Model): name = models.CharField(db_column='PersonName', max_length=255) age = models.IntegerField(db_column='PersonAge')
You are now required to change field name to let’s say identifier, but your manager sometimes takes a look at raw database and wants the db_column to change also. If you just change your models.py file to this:
class Person(models.Model): identifier = models.CharField(db_column='PersonID', max_length=255) age = models.IngeterField(db_column='PersonAge')
django will generate a migration that won’t quite suit your needs, because it will remove and create the column again, which will cause you to lose all the data.
The solution is quite simple
- Create an empty migration and open up the file.
$ python manage.py makemigrations --empty yourappname
- Use the RunSQL method filling the state_operation param ex.:
# -*- coding: utf-8 -*- # Generated by Django 1.11 from __future__ import unicode_literals from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ ('data', '0001_initial'), ] operations = [ migrations.RunSQL( "ALTER TABLE `Person` CHANGE COLUMN `PersonName` `PersonID` VARCHAR(255) NOT NULL", state_operations=[ migrations.AlterField( model_name='person', name='name', field=models.CharField(db_column='PersonName', max_length=255) ), migrations.RenameField( model_name='person', old_name='name', new_name='identifier' ) ] ) ]
- Apply migration.
This way all our data will be preserved and your co-workers will be able to quickly sync their apps.