Easiest way to rename a model using Django/South?

django, django-models, django-south, python, rename

Solution

To answer your first question, the simple model/table rename is pretty straightforward. Run the command:

./manage.py schemamigration yourapp rename_foo_to_bar --empty

(Update 2: try `--auto` instead of `--empty` to avoid the warning below. Thanks to @KFB for the tip.)

If you're using an older version of south, you'll need `startmigration` instead of `schemamigration`.

Then manually edit the migration file to look like this:

class Migration(SchemaMigration):

    def forwards(self, orm):
        db.rename_table('yourapp_foo', 'yourapp_bar')


    def backwards(self, orm):
        db.rename_table('yourapp_bar','yourapp_foo')   

You can accomplish this more simply using the `db_table` Meta option in your model class. But every time you do that, you increase the legacy weight of your codebase -- having class names differ from table names makes your code harder to understand and maintain. I fully support doing simple refactorings like this for the sake of clarity.

(update) I just tried this in production, and got a strange warning when I went to apply the migration. It said:

The following content types are stale and need to be deleted:

    yourapp | foo

Any objects related to these content types by a foreign key will also
be deleted. Are you sure you want to delete these content types?
If you're unsure, answer 'no'.

I answered "no" and everything seemed to be fine.

Problem

I've been hunting for an answer to this on South's site, Google, and SO, but couldn't find a simple way to do this. I want to rename a Django model using South. Say you have the following: ``` class Foo(models.Model): name = models.CharField() class FooTwo(models.Model): name = models.CharField() foo = models.ForeignKey(Foo) ``` and you want to convert Foo to Bar, namely ``` class Bar(models.Model): name = models.CharField() class FooTwo(models.Model): name = models.CharField() foo = models.ForeignKey(Bar) ``` To keep it simple, I'm just trying to change the name from `Foo` to `Bar`, but ignore the `foo` member in `FooTwo` for now. What's the easiest way to do this using South? - I could probably do a data migration, but that seems pretty involved. - Write a custom migration, e.g. `db.rename_table('city_citystate', 'geo_citystate')`, but I'm not sure how to fix the foreign key in this case. - An easier way that you know?

Original source

Related problems