Django - How to rename a model field using South?

Jonathan Source

I would like to change a name of specific fields in a model:

class Foo(models.Model):
    name = models.CharField()
    rel  = models.ForeignKey(Bar)

should change to:

class Foo(models.Model):
    full_name     = models.CharField()
    odd_relation  = models.ForeignKey(Bar)

What's the easiest way to do this using South?



answered 8 years ago googletorp #1

You can use the db.rename_column function.

class Migration:

    def forwards(self, orm):
        # Rename 'name' field to 'full_name'
        db.rename_column('app_foo', 'name', 'full_name')

    def backwards(self, orm):
        # Rename 'full_name' field to 'name'
        db.rename_column('app_foo', 'full_name', 'name')

The first argument of db.rename_column is the table name, so it's important to remember how Django creates table names:

Django automatically derives the name of the database table from the name of your model class and the app that contains it. A model's database table name is constructed by joining the model's "app label" -- the name you used in startapp -- to the model's class name, with an underscore between them.

In the case where you have a multi-worded, camel-cased model name, such as ProjectItem, the table name will be app_projectitem (i.e., an underscore will not be inserted between project and item even though they are camel-cased).

answered 8 years ago sjh #2

I didn't know about db.rename column, sounds handy, however in the past I have added the new column as one schemamigration, then created a datamigration to move values into the new field, then a second schemamigration to remove the old column

answered 4 years ago donturner #3

Here's what I do:

  1. Make the column name change in your model (in this example it would be myapp/
  2. Run ./ schemamigration myapp renaming_column_x --auto

Note renaming_column_x can be anything you like, it's just a way of giving a descriptive name to the migration file.

This will generate you a file called myapp/migrations/ which will delete your old column and add a new column.

Modify the code in this file to change the migration behaviour to a simple rename:

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Renaming column 'mymodel.old_column_name' to 'mymodel.new_column_name'
        db.rename_column(u'myapp_mymodel', 'old_column_name', 'new_column_name')

    def backwards(self, orm):
        # Renaming column 'mymodel.new_column_name' to 'mymodel.old_column_name'
        db.rename_column(u'myapp_mymodel', 'new_column_name', 'old_column_name')

answered 4 years ago ancho #4

  1. Add south to your installed apps in project setting file.
  2. Comment out the added/modified field/table.
  3. $ Schemamigration <app_name> --initial
  4. $ migrate <app_name> --Fake
  5. Un-comment the field and write the modified one
  6. $ Schemamigration --auto
  7. $ migrate <app_name>

If you are using 'pycharm', then you can use 'ctrl+shift+r' instead of '' , and 'shift ' for parameters.

answered 3 years ago Dmitrii Mikhailov #5

Django 1.7 introduced Migrations so now you don't even need to install extra package to manage your migrations.

To rename your model you need to create empty migration first:

$ makemigrations <app_name> --empty

Then you need to edit your migration's code like this:

from django.db import models, migrations

class Migration(migrations.Migration):

dependencies = [
    ('yourapp', 'XXXX_your_previous_migration'),

operations = [

And after that you need to run:

$ migrate <app_name>

Just change the model and run makemigrations in 1.9

Django automatically detects that you've deleted and created a single field, and asks:

Did you rename model.old to (a IntegerField)? [y/N]

Say yes, and the right migration gets created. Magic.

comments powered by Disqus