Thursday, September 27, 2012

Django app reset (with south)

When developing a new Django app, it is common to make lots of changes in the models.py module.
In order to actually test the new app, you need to update the database with the new schema.
However, Django's syncdb does not update existing tables, only adds missing ones. 

There are a few database migration tools out there, but south is by far the most common one.
South excels on small changes, like adding a field or removing a constraint. In the early stages of app development, however, you might make rapid large changes and in the same time, not care too much about the existing data in the database (for that particular app).

So in the process of your development, you might want to do some kind of "app resetting", meaning - 'drop all the tables for this app and recreate them according to the new models definition'.
As common as it seemed to me, I couldn't find a solution for that procedure in neither the Django native api, nor in the community.
The closest options are sqlclear, which prints the sql statements to drop tables for an app and flush, which actually resets the entire database. Obviously these solutions are not south-friendly.

But I wanted something that actually resets a single app and also plays nicely with south.

Enters "south_reset", a management command that is just a few south commands sewn together, but I still found it useful enough to share.

The usage is pretty straight forward, just list the app names you want to reset.
The optional "soft" flag means that the migrations are merged to a single initial migration without actually running them (just faking it),  so the data persists for the app. This is useful when you make lots of migrations and you want to get rid of the clutter, but still keep the existing data in the database.

Note that you should be very careful with this command if you are deploying the code somewhere, you might get ghost migrations.

So, with no further ado, here is the gist:

If you are not familiar with management commands, you need to put this script under a "management/commands" folder in any of your apps. more information here.

5 comments:

  1. Excuse my ignorance, but can't you just do a DROP DATABASE and then manage syncdb?

    ReplyDelete
    Replies
    1. You can, but that would delete all the data in ALL the apps (including the superuser in your project, for example).

      Delete
  2. Thank you for this. Fits my needs perfectly!

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Thanks for this, here's my modified version that doesn't coalesce all existing migrations. It just does a 'python manage.py sqlclear | python manage.py dbshell' and then clears the south migration history for the given app:

      https://gist.github.com/3998773/

      Delete