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?
db.rename_table('city_citystate', 'geo_citystate')
, but I'm not sure how to fix the foreign key in this case.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.