I use South on a fairly substantial django project (35 models, 85+ migrations). After around a few dozen migrations we got really frustrated with south. We still use south, but now run all migrations via db.execute(""CREATE ... """) with manual SQL rather than using the south models and the south wrappers. There were too many instances when there would be some little thing wrong, and we would get long, very hard to debug error messages. Also a number of times I would get my local install into a weird state where I could not run migrations, and I'd have to manually patch up. By doing straight SQL I always know exactly what is running, and so it is both easier to debug locally and feels safer to run against the prod data.
When we switched to db.execute, we lost the ability to do backwards migrations, but that's ok. Backwards migrations are really, really dangerous. In fact, deleting columns, ever, is really dangerous. If you are deleting data permanently it is always better to hand craft precisely what you want to do, and have everyone look it over, rather than running a backwards migration.