Django Diaries / 9th Aug 2013

Routing and Prepping

It's been a slightly slower pace of work the last few weeks because of a friend's wedding on the wonderful island of Madeira (you can read my Trip Notes if you want to know more), but there were still a few notable changes.


The thing I'm most excited about is database router support for migrations. South is especially bad at multi-database migrations, supporting only the bare minimum to even function, and so I wanted to improve that state of affairs for django.db.migrations.

Since syncdb had just been deprecated in my branch, the allow_syncdb method on database routers seemed a little out of place. The idea was still sound - say which models can be installed in each database - but the name and usage needed adapting.

Thus, it's been renamed to allow_migrate, and the migration operations have been updated to respect it. Because the new codebase operates on models (rather than tables, like South does), it can just call the router inside every operation, see what it's allowed to do, and just do it.

There's a few caveats, of course; you can't include models into a database without also including the ones they depend on, and if you change the behaviour of the router partway through a model's existence you'll get undefined results. Still, it's a big step towards what people expected South should do all along.

Permissions and ContentTypes

These are also a problem with old South thanks to its very shallow integration with Django; as a third-party project, it was very hard to get the right hooks in place to make ContentTypes and Permissions work as expected.

Now they're triggered from the post_migrate signal, and should work exactly as before for apps with and without migrations. I'm not the world's biggest fan of ContentType - I really think it should go away eventually - but it's here for now, and it has to be supported.

The Merge

That, along with some polishing and documentation tweaks, led me to proposing the merge on django-developers today. Plenty of code review points have already come in, and there's still more to come, I'm sure, but the initial feedback looks to be mostly about polish, which is a good sign.

If you're interested, the pull request is #376 - feel free to comment if you see something wrong. The documentation isn't complete and won't be finished until after the merge, but feedback on what sort of documentation people would like to see would be great. I suspect a tutorial update is in my future.

Some people have questioned why I'm merging now, with a 90% complete feature, rather than when it's done. The answer is simple: reducing extra work. The longer I stay branched off from Django, the further my branch and master deviate, and the more work it is to keep them in sync.

In fact, the whole topic of long-running branches is something I'd love to write up at some point. It differs by software type, especially; at Lanyrd, we write most things in or very close to master, and just hide it behind feature flags, but that's a small, close-knit team on a user-facing product. On something like Django, this is the only way, but it would be interesting to see if there was some way to improve it.