As you’ve all been hearing, we spent last week building Matt (Multi Account Twitter Tweeter). We’re absolutely thrilled with the way it went. We finished on time, we got some great feedback, and we learned a lot. But everybody’s been asking: What was it like to build it? What went wrong? How did you guys find Django? Why does Elliott spend all day snacking?
Building Matt was great fun. Python is a great language and Django is really good web development framework. We considered using other options (principally Symfony) and a language we both know well (PHP) but in the end we decided that it would be all part of the fun if we made it tricky!
Remember, this is our experience with Django and Python, and as a result it’s based on the comparison between these and our previous environments.
Python is fun to write and you end up with beautiful code. As the libraries pre-exist on the server a Django project can afford to be small and lightweight. It’s also very fast! Once we realised that Apache’s KeepAlive had yet to be switched off, The Mattinator ran like lightning, even with all the traffic from the launch.
When it came to coding, we noticed some differences between PHP and Python. The one I found interesting was the way in which Python allows you to change variables without using explicit “getters” and “setters”. But Python, like Ruby, has a very clever way of getting around writing all the code required. Tech-minded readers, see Ryan Tomayko’s example. The specific differences between the inner workings of both packages is another blog post in itself, and a techy one at that.
Template Filters in Django are a great way of elegantly including pure Python code into the light-weight template language. Using the |, or ‘pipe character’, you can filter data through a python function described in a special template tags library. This is a great example of the DRY principle – write a template tag once, and use it throughout your project. Django is even kind enough to come with a set of template tags ready for you to use. (Remember to uncomment the line in your settings.py file to enable custom template tag libraries or you’ll be tearing your hair out wondering why they aren’t being included.) You can then pipe your function through several different template tags to get the desired effect. For example, Django escapes HTML posted in your tweets. We used:
to escape the tweet status immediately – removing the HTML from the message so we can safely show it. We then add the @reply tags, then filter it through “safe” so as to avoid Django’s auto-escaping removing our special @reply links. Pipes are used in the UNIX command line to pipe data from one application to another, so they make sense in this context too.
I’m a big fan of convention over configuration, and it seems to me that Django is quite flexible whereas other frameworks – such Symfony and Rails – are more strict. While there’s a huge learning curve for strict frameworks, it definitely comes in handy when you have lots of developers working on a large project. New developers can just jump straight in and know exactly how everything works. A pre-defined structure is also a way of keeping things from getting out-of-hand later on. As many developers have found, it’s very easy to end up with a great big messy structure – imposing strict rules on your developers is a great way of keeping this in check.
There also aren’t any environments available in Django. In Symfony, environments for development and production are available straight out of the box. This means that you can customize settings for production, testing and development, as well as any other implementations you’re planning – like ‘staging’ or ‘windows_machine’ or ‘elliotts_server_under_the_stairs_next_to_the_cat_food’. So you can edit the settings for all three environments locally, and keep exactly the same source code for all three versions, to be used automatically. With Django you have to set your source control method of choice to ignore your configuration files. Django only has one, settings.py, so this wasn’t too tricky – although we’d have appreciated being able to set up a settings-dev.py and settings-prod.py, or the equivalent, just for consistency.
And try as we might, we couldn’t get Python to connect to MySQL on OSX. If this is easily possible, please let us know! But we didn’t have much time, so we ran with SQLite3 on our local machines, to be switched out for MySQL on the live server. That was another setting we had to change for the live environment – but the Django ORM, which keeps all the database stuff separate, did its job flawlessly, and there were no SQL changes to make.
Coming from a PHP background, there are some great IDEs available, which are the editing programs used to edit your source files (mad props to Zend Studio) which read through your code and can auto-complete what you’re writing very intelligently. PHPDoc code, which is automatically written by Propel in the Symfony model files, can be read by the API in order to discover and propagate object types. This makes developing much easier, especially in a new language, because as you’re writing you get a list of methods available to you for any object. Although Textmate is a fantastic editor, this was something that I missed. Perhaps it’s a mark against me as a developer for not memorizing all the functions available in Django and Python, but I like to be reminded that I’m on the right track without having to switch to the browser to debug what I’ve written. This may be simply because PHP is such a wide-spread language that more tools have been built for it.
Things we discovered:
Turn KeepAlives OFF. When we first put Matt live, we had Apache’s KeepAlive directive set to its default, ON. This meant that Apache would keep its connections to each client computer alive, which meant that Matt ran slower, and slower, and slower. Some hosts may set this automagically for you – but it pays to check your httpd.conf settings just in case.
If I’ve underestimated Django or Python, then please let me know! It’s only because we spent only four days working with both. All frameworks have their good and bad points – it comes down to a personal preference on language and structure. I think that the framework war will be waged for some time to come. The best advice I got was to pick a popular one, and get good at it. Once you get really good, you can do what you need to do very quickly and efficiently, and maintain it effectively. It’s all too easy to say “Framework X is better than Framework Y because Z” (as I’m sure we’re about to see in the comments below), but I think it’s getting to the stage where they’re all pretty good at spitting out HTML.
I like Django, and Python. I really do. They’re nice, and easy to use, very fast, and I don’t have any real problems with either. They’re tackling the opposition, an entrenched PHP developer-base, with great results. But it comes down to the real-world advantages of using them, and the real-world tools currently available – an abundance of PHP developers, great PHP IDEs, and easy PHP hosting. It also does come down to personal preference, and the requirements of the job. So there’s no real way of telling you which one to use.
But this is all set to change at any point. There are many other frameworks all vying for their share – what do you think?