Django migration strategy for renaming a model and relationship fields
Question: I'm planning to rename several models in an existing Django project where
there are many other models that have foreign key relationships to the models
I would like to rename. I'm fairly certain this will require multiple
migrations, but I'm not sure of the exact procedure.

Let's say I start out with the following models within a Django app called
`myapp`:

    
    
    class Foo(models.Model):
        name = models.CharField(unique=True, max_length=32)
        description = models.TextField(null=True, blank=True)
    
    
    class AnotherModel(models.Model):
        foo = models.ForeignKey(Foo)
        is_awesome = models.BooleanField()
    
    
    class YetAnotherModel(models.Model):
        foo = models.ForeignKey(Foo)
        is_ridonkulous = models.BooleanField()
    

I want to rename the `Foo` model because the name doesn't really make sense
and is causing confusion in the code, and `Bar` would make for a much clearer
name.

From what I have read in the Django development documentation, I'm assuming
the following migration strategy:

# Step 1

Modify `models.py`:

    
    
    class Bar(models.Model):  # <-- changed model name
        name = models.CharField(unique=True, max_length=32)
        description = models.TextField(null=True, blank=True)
    
    
    class AnotherModel(models.Model):
        foo = models.ForeignKey(Bar)  # <-- changed relation, but not field name
        is_awesome = models.BooleanField()
    
    
    class YetAnotherModel(models.Model):
        foo = models.ForeignKey(Bar)  # <-- changed relation, but not field name
        is_ridonkulous = models.BooleanField()
    

Note the `AnotherModel` field name for `foo` doesn't change, but the relation
is updated to the `Bar` model. My reasoning is that I shouldn't change too
much at once and that if I changed this field name to `bar` I would risk
losing the data in that column.

# Step 2

Create an empty migration:

    
    
    python manage.py makemigrations --empty myapp
    

# Step 3

Edit the `Migration` class in the migration file created in step 2 to add the
`RenameModel` operation to the operations list:

    
    
    class Migration(migrations.Migration):
    
        dependencies = [
            ('myapp', '0001_initial'),
        ]
    
        operations = [
            migrations.RenameModel('Foo', 'Bar')
        ]
    

# Step 4

Apply the migration:

    
    
    python manage.py migrate
    

# Step 5

Edit the related field names in `models.py`:

    
    
    class Bar(models.Model):
        name = models.CharField(unique=True, max_length=32)
        description = models.TextField(null=True, blank=True)
    
    
    class AnotherModel(models.Model):
        bar = models.ForeignKey(Bar)  # <-- changed field name
        is_awesome = models.BooleanField()
    
    
    class YetAnotherModel(models.Model):
        bar = models.ForeignKey(Bar)  # <-- changed field name
        is_ridonkulous = models.BooleanField()
    

# Step 6

Create another empty migration:

    
    
    python manage.py makemigrations --empty myapp
    

# Step 7

Edit the `Migration` class in the migration file created in step 6 to add the
`RenameField` operation(s) for any related field names to the operations list:

    
    
    class Migration(migrations.Migration):
    
        dependencies = [
            ('myapp', '0002_rename_fields'),  # <-- is this okay?
        ]
    
        operations = [
            migrations.RenameField('AnotherModel', 'foo', 'bar'),
            migrations.RenameField('YetAnotherModel', 'foo', 'bar')
        ]
    

# Step 8

Apply the 2nd migration:

    
    
    python manage.py migrate
    

* * *

Aside from updating the rest of the code (views, forms, etc.) to reflect the
new variable names, is this basically how the new migration functionality
would work?

Also, this seems like a lot of steps. Can the migration operations be
condensed in some way?

Thanks!


Answer: So when I tried this, it seems you can condense Step 3 - 7:

    
    
    class Migration(migrations.Migration):
    
        dependencies = [
            ('myapp', '0001_initial'), 
        ]
    
        operations = [
            migrations.RenameModel('Foo', 'Bar'),
            migrations.RenameField('AnotherModel', 'foo', 'bar'),
            migrations.RenameField('YetAnotherModel', 'foo', 'bar')
        ]
    

You may get some errors if you don't update the names where it's imported e.g.
admin.py and even older migration files (!)

