For a while now I’ve been pretty embarrassed by this site. Not by the visual design, or the functionality (though some bits have been lost along the way, for reasons that will become obvious in a moment), but by the fact that it was old. As in, over five years old. It was running on a bunch of ancient code that I’d written a long, long time ago, on an ancient Subversion checkout of Django — for the historians in the audience, it was pre-queryset-refactor — and was, frankly, not particularly well-built to begin with.
I’ve lately been feeling the same way about some other public-facing projects I’ve worked on, which just added to the feeling of embarrassment: everything was too old, or too badly-written, or both, which is a major deterrent to feeling motivated to work on and do things. Especially since something written for an ancient version of Django can’t really take advantage of new tools or features.
But, finally, that’s changing.
Shiny and new
First up, if you’re seeing this, then you’re seeing a brand-new codebase in live deployment. You can check out the full list of technology in use if you’re interested, but here are the highlights:
- I’m now running on Django 1.5, meaning I’ve got access to a lot more convenience, both from the framework itself and from the ecosystem of stuff that runs on Django.
- I’m now running on Python 3. Since I’ve made the code available publicly, I’ve done my best to make it compatible with Python 2 as well, but Python 3 was and is the primary goal.
- I’m actually using something close to modern deployment techniques — everything except a local settings file (which contains sensitive or site-specific things like database info,
SECRET_KEY, etc.) lives in a repository on GitHub, and is pulled into a virtualenv on the server, running behind the one-two combo of nginx and gunicorn.
Getting there was a bit of effort, and sometime soon I’ll probably write about it in detail, but the biggest takeaway is that getting everything to run on Python 3 was… almost ludicrously easy.
Since that bears repeating: getting up and running on Python 3 was easy. If you go take a look through the code for my blog app, I think you’ll find all of about three lines that exist to take care of Python 2/3 compatibility, and they’re all from stuff that’s built in to Django, which has excellent documentation on how to write code that works on Python 2 and 3. Granted, a blog isn’t a terribly complex application, but most useful applications aren’t really terribly complex.
So if you’ve been holding off from a Python 3 migration for fear that it would be too difficult, or that the library support wasn’t there, you should probably stop being afraid. In my case, there was one library that wasn’t quite compatible, so I forked it, made a quick change, and deployed from that.
Part of getting to this point, of course, was porting some old apps — besides the blog — that I’d written a long time ago. It’s been a bit of a busy summer, so I’ve been taking that at a pretty leisurely pace. I actually started with something that I don’t even personally use anymore, a pretty simple module that does web-color-format conversions. That one actually just worked out of the box on Python 3.3, so I ended up not having to do anything. I’ll probably roll a new release of that soon, though, just to update the documentation and add the Python 3 trove classifiers (and clean up its PyPI listing while I’m in there).
Then I moved on to an actual Django application, though again a pretty simple one. It turned out to need a minor tweak for Python 3 string compatibility, and then it also just worked. My third Python 3 port was an application that I actually use on this site — django-contact-form powers my contact form.
That one was a bit more involved, not because of Python issues, but because I went ahead and updated it to use class-based views. The next release of that one will probably add proper i18n support, if there’s interest; someone submitted a pull request years ago for a translation, but I hadn’t got round to it in time to actually have it work.
Altogether this has been a few weeks’ worth of my evening and weekend time (and, with two conferences, a work trip, and a couple of personal trips recently, I haven’t had a ton of evening/weekend time to spend on things). This morning I flipped the switch on the DNS, pointing to a new server running the Python 3 codebase.
The future (this site)
It feels really good to finally be up-to-date (at least for a little while; Django 1.6 is in beta already, and I do plan to upgrade as soon as possible after it releases, since it’s looking pretty hot). it feels really good to look at this site and not be embarrassed by how old and cruddy the code is. It feels good not to be discouraged from writing by knowing that I really ought to get around to rewriting and upgrading everything. And that’s a pretty powerful motivator.
My next significant project is probably going to be switching over to Persona for authentication; I’ve already had a chance to use it and see it in action (at the day job, we’ve been using Persona auth in production for a while), and lately I’ve been reading up a bit on how it works. There’s another whole post lurking in that, but it’s enough to say that I’ve been a lifelong skeptic of single-sign-on and federated-identity systems, and Persona has actually won me over. There’s Django integration available (with some Python 3 hiccups that I’ve reported and plan to see if I can help out with, so mkelly won’t kill me for reporting and running away), and it actually is just stupidly easy to plug in and use.
I’m also going to try an experiment with writing, since I desperately miss doing that. A few years ago I tried (and, due to some surprise travel plans, failed) to keep up with a “post-a-day” fad that a bunch of people were doing; I know I can’t maintain that sort of pace, but I am going to try for at least one a week, since I’ve got a few topics queued up and no further reason to feel embarrassed about my own site.
The future (other projects)
Meanwhile, I’ve been doing a lot of thinking about the collection of Django-related apps I’ve put out over the years, and debating just what I want to do with them. Some are as embarrassingly old as this site was. Some are even older. Some of them solve problems that no longer exist, or are no longer relevant. So I’ve been trying to make some tough decisions, and I’m not entirely done with that.
My personal philosophy on Django application design was articulated in the first public Django-related talk I ever gave (at the very first DjangoCon, no less). The slides are here, but the bullet-point version of that philosophy is:
- Do one thing, and do it well.
- Don’t be afraid to write a bunch of apps.
- Write for flexibility.
- Build to distribute.
Those are still pretty solid guiding principles, though these days I’d be inclined to add a couple more to the list:
- Solve an unsolved problem.
- Write something you personally care about.
That last one is a bit hand-wavy, since being paid to write code is certainly a motivation to care (and has caused me to care about things I otherwise never would have), but mostly I think it’s a mistake to be writing and trying to maintain something that you don’t personally have a stake in.
In case you can’t guess, this is the segue into talking about the elephant in the room: django-registration.
Many years ago, django-registration was my pride and joy. It was extensible and flexible despite also being clean and simple, it exemplified what I thought was right about how to write Django applications and it was, by a large margin, the most popular piece of personal code I’d ever written. And then time passed. It started growing, doing more things, getting more unwieldy, and generally being much less of what I’d consider to be good code. And then it started to rot.
Django 1.5 compatibility was a sore spot for a while, because — for multiple reasons — I just didn’t have the time to even review pull requests other people were sending in. And I was getting spammed, multiple times a day, by endless “+1” and “why isn’t this merged yet” comments that I couldn’t do anything about, which certainly didn’t help. I posted a comment mentioning that I had a partial rewrite done and would wrap it up at the PyCon sprints; that became django-registration 1.0, which was released right about then.
Except there were still issues:
- Custom user-model support is a nightmare. Not because Django made it hard, but because that use case is the metaphorical straw that finally broke the camel’s back. At this point I think django-registration just tries too hard to do too much. It no longer does just one thing, and no longer does anything particularly well. Especially not support for custom user models.
- Other options have appeared which fill the same gap, so django-registration no longer solves an unsolved problem.
- I no longer use django-registration in any capacity. For as far as I can see into the future, everything I’m going to be doing either has wildly different requirements or will be Persona-based, and user registration is a whole different world with Persona.
All of which adds up to a sad but necessary conclusion: I should no longer be the maintainer of django-registration. As of today, I’m accepting proposals to hand it off; if you’re interested, get in touch and we’ll talk.
As for my other apps:
- As mentioned, django-contact-form and django-flashpolicies have shiny new releases out recently, with Django 1.5 and Python 3 support. They’re also the sort of “do one thing and do it well” apps that I love to work on, they fill useful niches, and I have an interest in seeing them stay up-to-date. So I’ll be maintaining them for the foreseeable future.
- django-profiles, which used to be django-registration’s favorite companion app, is effectively dead. The use case for it is increasingly irrelevant (you no longer need to use the cumbersome user-profile system, since you can just as easily build your own custom user model), and like django-registration, trying to support everything people now want from an app like that is probably not going to be pretty. If someone wants to take it over, they’re welcome to give it a try, but otherwise I intend to simply let it die.
- django-comment-utils literally has no reason to exist at this point. Its big selling point — a simple framework for customizable moderation rules — has been part of Django’s own comments app for a while now, and was pulled in almost verbatim. So that one’s dead.
- Which leaves only one non-work-related app (I do have one other project on github, but it’s a one-off that was written to fill a need at work): django-template-utils, which was last updated in 2007. So you can and should be forgiven if you’ve never heard of it; it provided a few things that seemed handy at the time (some useful template node classes for common use cases, an extensible markup-application system, and a generic content-retrieval framework), but I have no earthly idea whether any of them are still useful today. So this one I’m still thinking about.
In the meantime, I’m going to bask a bit in the glow of a shiny new Python-3-powered site, and put my time into getting ready for DjangoCon. I’ve been hitting the conference circuit pretty hard this summer, trying to ease back into the community after basically being devoured by work and non-tech-related things for over a year, and DjangoCon is the last stop on that tour. For the first time ever I’m not going to be speaking (though I am putting together a proposal for PyCon next year, so if you enjoy hearing my voice you can hopefully get your fix next spring in Montréal), but I’ll be there for the full conference + sprints and aiming to socialize and get back into the flow of things.