Part 5: Teams and Workflow
Migrations are all about improving the workflow for the developers and database administrators of projects, and we think it's very important that it doesn't add too much overhead to your daily coding, while at the same time reducing headaches caused by the inevitable changes in schema every project has.
Firstly, note that migrations aren't a magic bullet. If you've suddenly decided you're going to rearchitect your entire database schema, it might well be easier to not write migrations and just start again, especially if you have no production sites using the code (if you do, you might find custom serialisation/unserialisation to be a better way of saving your data).
With that in mind, migrations are really something you should be using the rest of the time. Hopefully, the previous parts of the tutorial have got you familiar with what can easily be achieved with them; we've tried to cover a good percentage of use cases, and if you think something should be included, don't hesitate to ask for it.
As a developer, you should be doing things in this order:
- Make the change to your models.py file (and affected code, such as post_syncdb signal hooks)
- Make the migration
- Rinse, repeat.
Don't try to make migrations before you make the changes; this will both invalidate the frozen model data on the migration and make startmigration --auto think nothing has changed. If you're making a large change, and want to split it over several migrations, do each schema change to models.py separately, then make the migration, and then make the next small change.
Note that the ./manage.py schemamigration command has an --update mode that allows you to further iteratively refine your migration as such changes become necessary while working on your code. It is preferable to distribute a single migration for each atomic code change (a particular bug fixed, a new feature), then half a dozen migrations that could be merged into one. Remember that the purpose of migrations is to replay database changes on multiple machines; a separate migration is not required for changes that have only been applied locally.
While migrations for an individual developer are useful, teams are perhaps the real reason they exist. It's very likely more than one member of your team will be making database changes, and migrations allow the other developers to apply their schema changes effortlessly and reproducibly.
You should keep all of your migrations in a VCS (for obvious reasons), and encourage developers to run ./manage.py migrate if they see a new migration come in when they do an update or pull.
The issue with teams and migrations occurs when more than one person makes a migration in the same timeslot, and they both get committed without the other having been applied. This is analogous to two people editing the same file in a VCS at the same time, and like a VCS, South has ways of resolving the problem.
If this happens, the first thing to note is that South will detect the problem, and issue a message like this:
Inconsistent migration history The following options are available: --merge: will just attempt the migration ignoring any potential dependency conflicts.
If you re-run migrate with --merge, South will simply apply the migrations that were missing out-of-order. This usually works, as teams are working on separate models; if it doesn't, you'll need to look at the actual migration changes and resolve them manually, as it's likely they'll conflict.
The second thing to note is that, when you pull in someone else's model changes complete with their own migration, you'll need to make a new empty migration that has the changes from both branches of development frozen in (if you've used mercurial, this is equivalent to a merge commit). To do so, simply run:
./manage.py schemamigration --empty appname merge_models
(Note that merge_models is just a migration name; change it for whatever you like)
The important message here is that South is no substitute for team coordination - in fact, most of the features are there purely to warn you that you haven't coordinated, and the simple merging on offer is only there for the easy cases. Make sure your team know who is working on what, so they don't write migrations that affect the same parts of the DB at the same time.
Complex Application Sets
It's often the case that, with Django projects, there is a set of apps which references each others' models.py files. This is, at its truest form, a dependency, and to ensure your migrations for such sets of applications apply sanely (i.e. the migrations that create the tables in one app happen before the migration that adds ForeignKeys to them in another app), South has a :ref:`Dependencies <dependencies>` feature. Once you've added dependencies to your migrations, South will ensure all prerequisites of a migration are applied before applying the migration itself.