Aug 12, 2011

Django: How and why to use migrations. Django-South.

Hi there guys and we're here to talk about migrations today. My app grown to complex app with profiles, social registration permits and so on. First time I've decided to make myself a simple app. Now it became complex enough and contains enough code to need code comments :). Anyway Migrations is a process anybody someday will need. I thought it's hard to learn or understand, but it's not.

Main point is that you:
- save your current database tables structure
- change your model tables
- scan for differences and create script
- then write changes to your database with automatically generated python script.

Sound's simple? I't not all so simple in fact. App that you need to learn is Django-south. Its main objectives are to provide a simple, stable and database-independent migration layer to prevent all the hassle schema changes over time bring to your Django applications. It has quite understandable tutorial here.

So if you're tired of ALTER'ing your tables and writing code to python Sqlite console or editing raw SQL, go get yourself a copy of south. It's an app that IMHO everybody should use/hear/understand.

It is meant to change old one and quite simple command 'manage.py syncdb' someday. For now go get yourself this tool and learn to use it. It took me about half an hour to understand basics.. So it's not hard (at first) :).

Brief look at usage:

1. Install app in some way. Use pip/easy_install script or simply put 'south' dir to your project root dir.
Add 'south', to your INSTALLED_APPS dictionary.
!IMPORTANT! you need to make syncdb after that. Another way wo will get an error with future commands.

2. Connect existing app's to migrations. Use command python manage.py convert_to_south myapp to convert your app from syncdb ready to south migratable. Or you can run python manage.py schemamigration newappname --initial to add south migrations ability to your new app. In general it will create directory 'migrations' inside your app directory.

3. Change your model. I dont think you need separate stop here. But... Just in case add some field to your django model like bollean or text and/or edit your existing field rather by adding 'null=True' for e.g.

4. Create your migration. It can be done by command python manage.py schemamigration newappname --auto to create your migration script. you can check it in your app's 'migrations' dir. It has numbers in the beginning with migration number.

5. Run your migration. It is done by command python manage.py migrate appname or even without an app name: python manage.py migrate to migrate all apps. Thats it.

Hope you'll never use 'syncdb' again for complex tasks like this. I'm adding it to my base developer tools. And you?

7 comments:

  1. How is that different from the manual?

    ReplyDelete
  2. It's a bit why do you need it and shorten a bit...

    ReplyDelete
  3. Hi
    I am using South but I am getting an error while running syncdb. 'no module named southregistration'. I have installed south using pip for python 2.7. and I have included south in INSTALLED_APP as well but still I am getting this error

    ReplyDelete
    Replies
    1. If Django doesn’t seem to pick this up, check that you’re not overriding INSTALLED_APPS elsewhere, and that you can run import south from inside ./manage.py shell with no errors.

      Please run the console from where you manage.py lives (environment if you're using virtualenv) and try to do:

      (virtualenv_name):projectdir username$ python
      Python 2.7.2 (v2.7.2:8527427914a2, Jun 11 2011, 15:22:34)
      [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
      Type "help", "copyright", "credits" or "license" for more information.
      >>> import south
      >>>

      IF you see any errors there then you've probably have not installed south... try to do:

      easy_install South

      Delete
  4. I have this when run migrate

    Running migrations for messenger:
    - Migrating forwards to 0001_initial.
    > messenger:0001_initial
    FATAL ERROR - The following SQL query failed: CREATE TABLE "messenger_message" ("id" integer NOT NULL PRIMARY KEY, "subject" varchar(100) NOT NULL, "date" datetime NOT NULL, "text" text NOT NULL, "sender_id" integer NOT NULL, "receiver_id" integer NOT NULL, "was_read" bool NOT NULL, "was_reply" bool NOT NULL)
    The error was: table "messenger_message" already exists
    ! Error found during real run of migration! Aborting.

    ! Since you have a database that does not support running
    ! schema-altering statements in transactions, we have had
    ! to leave it in an interim state between migrations.

    ! You *might* be able to recover with: = DROP TABLE "messenger_message"; []

    ! The South developers regret this has happened, and would
    ! like to gently persuade you to consider a slightly
    ! easier-to-deal-with DBMS (one that supports DDL transactions)
    ! NOTE: The error which caused the migration to fail is further up.
    Error in migration: messenger:0001_initial
    DatabaseError: table "messenger_message" already exists

    ReplyDelete
    Replies
    1. It tells you what to do. Database has the table named like so. Try renaming your model (resulting to different name of that table to migrate to) and either delete your destination table in the database. Other way you can not use south in case this has happened without really creating of that table before and entirely by south-migrations. It means you may have to have other database backend in order south to support migrations. E.g. more new MySQL or whatever you are using there as a database backend.

      Delete
    2. @Yordis - you can also use "--fake" for the initial migration if you are adding this to a legacy database that already has the initial sync'd tables in it. This means you don't have to drop everything.

      Delete