Django migrations and your new development environment
If you’re coming to Django from another framework where migrations are a first-class concept, the lack thereof is one of the first things you’ll notice about Django. The de facto standard for Django migrations is a third-party app called South. (There are others, see the full list on Django’s wiki.)
South makes it very easy to create migrations to add or remove columns, create tables, and perform other routine database schema updates. It keeps these migrations in sequential order, so your team can all perform the same updates in the same order on their workstations.
When you set up a new development environment (or server for that matter), you need to create the database schema your application requires. South expects you to do this by replaying your migration history:
$ ./manage.py syncdb $ ./manage.py migrate ... DatabaseException in 0003_some_ancient_migration
On a big, long-lived project, you’ll eventually have dozens or hundreds of migrations. These migrations are not regularly tested or even used by anyone. But if you use the above workflow, you’ll attempt to replay those dozens or hundreds of untested migrations on your system.
Code that is rarely used and never tested will rot; it’s just a matter of time. You’ll switch database versions, or some dependency will change, and your migrations no longer work. Really, is it even important that they work two years after they’re written? The purpose of a migration is to make a small, incremental change to an existing database, bringing it up to date. Forcing migrations to work over a period of years across a multitude of environments would require significant development effort, time which could be better spent on your product itself.
Normally, South hijacks your
syncdb command and does not allow Django
to create the tables for apps that normally use South’s migrations.
Fortunately there’s an easy workaround: South lets you bypass this
behavior and do a normal
syncdb with the
--all parameter. Run
syncdb will create tables for all of your apps, even those
that contain South migrations.
Simply doing this would leave your database schema and what South thinks about your database schema out of sync. To remedy this, follow it up with a faked migration run:
$ ./manage.py syncdb --all (Database is now ready to roll) $ ./manage.py migrate --fake (South pretends to run migrations and updates its internal state)
This is a much more reliable way to get a new environment up and running, and saves you the hassle of maintaining ancient migration code years after it was actually needed.
Note: If your migrations create data in the database (rather than just updating schema), skipping these migrations may leave your database setup incomplete. Normally, however, this will not be the case.