Renaming an app with Django and South

I agree with Laksham that you should avoid this situation. But sometimes, we have to. I've faced this situation in the past and I've managed it this way.

If you want to avoid losing data you can dump the old application data into a json file.

python manage.py dumpdata old_app --natural --indent=4 1> old_app.json

Note the --natural option that will force the content types to be exported with their natural keys (app_name, model)

Then you can create a small command to open this json file and to replace all the old_app references with the new_app.

Something like this should work

class Command(BaseCommand):
    help = u"Rename app in json dump"

    def handle(self, *args, **options):
        try:
            old_app = args[0]
            new_app = args[1]
            filename = args[2]
        except IndexError:
            print u'usage :', __name__.split('.')[-1], 'old_app new_app dumpfile.json'
            return

        try:
            dump_file = open(filename, 'r')
        except IOError:
            print filename, u"doesn't exist"
            return

        objects = json.loads(dump_file.read())
        dump_file.close()

        for obj in objects:
            obj["model"] = obj["model"].replace(old_app, new_app, 1)

            if obj["fields"].has_key("content_type") and (old_app == obj["fields"]["content_type"][0]):
                obj["fields"]["content_type"][0] = new_app

        dump_file = open(filename, 'w')
        dump_file.write(json.dumps(objects, indent=4))
        dump_file.close()

Then rename the application, change the name in INSTALLED_APPS.

Then, you should remove all south migrations, regenerate and apply an initial migration for the new app. Then run the SQL command:

update django_content_type set app_label='new_app' where app_label='old_app'

Then launch a south migrate for the new app in order to create the tables and load the json file.

python manage.py loaddata old_app.json

I've done something similar on a project and it seems to work ok.

I hope it helps


It is possible to rename an app. As example project, see:

https://github.com/ASKBOT/django-south-app-rename-example

Basically, there are 2 migrations. First the tables are renamed using a db.rename_table(), and next the content types are updated. This can be combined into one migration by checking for if not db.dry_run:. See How do I migrate a model out of one django app and into a new one? for an example of that.

For a initial migrations, you can directly rename the existing tables, if they are there:

if 'old_app_table_name' in connection.introspection.table_names():
    db.rename_table('old_app_table_name', 'new_app_table_name')
else:
    # Create new app tables directly.

For tables with more migrations, you may need to check whether the old migration name was already applied:

from south.models import MigrationHistory
if MigrationHistory.objects.exists(app_name='old_app', migration='0001_initial'):
    return

Lastly, I recommend using an IDE (e.g. a PyCharm trial) to rename the package (right click, refactor -> rename on the package) because it will update all usages across the application for you, including the URLconf, settings and imports.


After some plugging away, I came up with this. Should take care of it. https://gist.github.com/jamesmfriedman/6168003