Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change column type with django migrations

Consider this structure:

some_table(id: small int)

and I want change it to this:

some_table(id: string)

Now I do this with three migrations:

  1. Create a new column _id with type string
  2. (datamigration) Copy data from id to _id with string conversion
  3. Remove id and rename _id to id

Is there a way to do this with only one migration?

like image 899
kharandziuk Avatar asked Dec 09 '14 17:12

kharandziuk


1 Answers

You can directly change the type of a column from int to string. Note that, unless strict sql mode is enabled, integers will be truncated to the maximum string length and data is possibly lost, so always make a backup and choose a max_length that's high enough. Also, the migration can't easily be reversed (sql doesn't directly support changing a string column to an int column), so a backup is really important in this one.

Django pre 1.7 / South

You can use db.alter_column. First, create a migration, but don't apply it yet, or you'll lose the data:

>>> python manage.py schemamigration my_app --auto

Then, change the forwards method into this:

class Migration(SchemaMigration):
    def forwards(self, orm):
        db.alter_column('some_table', 'id', models.CharField(max_length=255))

    def backwards(self, orm):
        raise RuntimeError('Cannot reverse this migration.')

This will alter the column to match the new CharField field. Now apply the migration and you're done.

Django 1.7 You can use the AlterField operation to change the column. First, create an empty migration:

>>> python manage.py makemigrations --empty my_app

Then, add the following operation:

class Migration(migrations.Migration):
    operations = [
        migrations.AlterField('some_model', 'id', models.CharField(max_length=255))
    ]

Now run the migration, and Django will alter the field to match the new CharField.

like image 143
knbk Avatar answered Oct 12 '22 13:10

knbk