portable perspectives

a blog about programming, life, universe and everything

Rails vs Django: a non biased yet useless comparison

Lately I've been making my hands a little bit dirty with django, and since I already did a little bit of Rails I think I'm entitled to do a small comparison. No, this is a lie. I'm entitled to do that because I have a blog and that's it.

The non biased assertion is due to the fact that I like both frameworks and I do love both languages, the useless one is well, because you will still have to evaluate the things by yourself , cause I am not an expert at either and I think that my few readers are smart enough to understand that choosing an infrastructure requires more work than reading a random blog entry.

Both frameworks use the new classic MVC pattern (even if in django's lingo it's called MTV you will notice that it is 99.9% the same), and both framework provide some othe features, so I'll just split the comparison by these concepts.

* Model * The model layer in django and rails is basically built out of classes that map to DB tables, but the things are slightly different.

The model in rails is comprised of two things: an SQL definition and a Ruby definition. Yes I know about Dr Nic's magic models. You can also create the database in pure ruby by using the wonderful migrations' system that rails provides, but the model is still built out of the pair DB structure + Ruby code. AFAIK django doesn't have yet something on the level of Rails migrations, that allows you to programmatically move back and forth in time easily.

Django uses a single definition in python with more metadata, and provides some useful python datatypes that are mapped transparently on the DBMS, so that a Post class can have a SlugField, while a Comment can have EmailField and IPAddressField. Yet, you can still go down to the SQL level if you want.

It seem to me that the support for validation is quite similar under the surface for both frameworks: you can validate single fields ot whole objects at different times and stack different validators.

One big flaw in current django's models is that they don't allow inheritance, and so if you have a lot of models that differ just slightly you can't save work using this approach. Rails' ActiveRecord gets a big plus for this, but this should be solved soon in django.

* "the thing that does *which" ** Rails calls the module that chooses which data to show the Controller. For some reason Django calls it the View whereas the Controller is the underlying support software.

Rails which is made of two elements: Controller objects and actions. A request for a page is processed so that it instantiates a Controller object and setups variables appropriately, then the action method is called. At the class level you can define behaviour shared between the various action with a nice syntax, but I don't particularly love the :except and :only things.

In django an action is just a function which takes a fixed argument, the request, and an optional set of named arguments. I love the way named arguments work in python and I think that this approach provides much more readability, but to have that in ruby we will have to wait for ruby 2.0 (or use evil.rb which doesn't feel enterprisey).

The only thing I dislike in django's view is that you have to explicitly point out to a template file when rendering a view, whereas rails' convention over configuration in this case relieves the user of a repetitive and non-interesting operation.

I also think that not having the class Foo < Controller boilerplate is better, but the bad news is that django doesn't do magic requiring of modules and you have to do it yourself, so everything balance out.

Both systems allow caching but (for what I understood) Django mostly uses time-based cache invalidation, while rails provides only an event-based expiring behaviour.

Anyway there are plugins for rails that allow time based invalidation, and I believe that it should be possible to expire something in an event-based fashion in django too, cause the underlying mechanics are the same (CACHE.set(key,val), CACHE.get(key) and CACHE.del(key)).

It seems that django doesn't provide the fine-grained caching control that rails has, allowing just a whole-page caching or forcing the user to resort to the low level cache api, which I think is a bad thing.

Finally, django uses exceptions to handle error codes, which I believe is a far better solution than rails :status=>code, because it allows breaking out of an action from an utility method. This allows, the refactoring control in utility methods, having shortcuts such as get_object_or_404(Class,key=val), which simplify the writing of views.

* "the thing that does _how_" * The actual showing of data is usually done in both frameworks through templates, which rails call Views. Django uses an interestint template language while rails uses ruby embedded in XHTML by deafult, but different templating engines can be used as plugins very easily.

Both allow the composition of smaller units to enhance reuse and ease of maintenance and it I believe that apart from personal preferences there are not big differences in this area.

* Other things * I think that the main differences in rails and django can be appreciated going away from the basic elements and looking at the rest of the platform, where the frameworks differ greatly.

First, django provides internationalization as a builtin concept while in django you're forced to use external libraries such as Globalize. Sadly, I am convinced that this is such an important feature that it must be builtin and it is an error not to have it, because to do it right the framework must be engineered around it. It must be also noticed that python's support for unicode (and other text encodings) in general is far more advanced than ruby's, which basically just kind-of-supports utf-8 (wait for ruby2, again).

Second, django's automatic generation of an administration facility, complete with authorization support and a bunch of space for customization is amazing. Again, there are modules for rails that provide this kind of behaviour, but having such a feature builtin makes it a foundation and a reference against which every programmer can code, which makes coee sharing easier.

In general django has builtin support for a lot of functionalities that are common in modern web apps, not only admin and auth, but also sitemaps, syndication, comments and much more.

Rails takes a minimalistic approach on this and pushes all this stuff in plugins. The rails community is producing plugins at an incredible rate, and even if not all of them are compatible and high quality code there is a lot of choice.

In the old days rails' plugins used to have some issues and this was the reason for the existence of things like rails engines but as of 1.2 this problems are not there anymore, Django allows code sharing through the integration of different apps which is what the admin above mentioned features are, and each of this add-on can contain something as easy as a textilize() function to a whole application such as a wiki or a blog.

There are not so much django apps as there are rails plugins, and I believe that this depends on 3 factors

  • smaller community
  • slightly harder sharing (in rails you just user script/plugin install and you're done)
  • less duplication The latter is hardly dependent on django coming with more batteries included, so for example you don't need a plugin for creating slugs because there is a lready a slugify() function.

* Conclusion * I wish rails had more batteries included, and that ruby was a little bit more like python (i.e. modules, named args, function decorator syntax). And I wish django used more conventions/less typing, and python was more like ruby (blocks, functions call without parenthesis, implicit self). but I still like both, pick your choice or even better try both. This at least will make you ready to write your own framework ;)

AddThis Social Bookmark Button

7 Responses to “Rails vs Django: a non biased yet useless comparison”

  1. rick Says:
    It seems to me that Django is more focused on content-heavy sites, like newspapers, magazines, etc (though, the svn code review system by the vmware guys is a great exception). I think some of the "batteries" that django includes for free would be inappropriate for a lot of Rails apps. That's okay, there are several auto-admin rails plugins popping up around the place. It's a delicate balancing act though. People call rails bloated, yet wish for more stuff out of the box. Another example of this is globalization. This is definitely important for a lot of folks, but we haven't seen a single right way to go for rails apps. Until that happens, that kind of stuff will likely be done in plugins like Globalize. Rails lets you rescue exceptions and return standard error codes too. Rails 2.0 includes nicer internals for setting your own response status for custom exceptions (in Rails 1.2 and below you're stuck overwring rescue_action_in_public in your controllers).
  2. riffraff Says:
    I don't think that rails is bloated so I'm biased :) But I agree that it's a question of balance, and that choices must be done carefully (the ActiveResource in/ActionWebService out swap is a perfect example of a good choice) but some things like syndication are so useful and reinvented so often that I believe they should be in the core. I bet there are more websites with a feed than websites using ajax :) BTW, I know I can use rescue_action* to handle exceptions, but it's more work for the developer that can just be take away. Glad to know it will come in rails2 :) Thanks for the thoughts and informations.
  3. Simon G. Says:
    Interesting article - Just a few comments:
    The only thing I dislike in django's view is that you have to explicitly point out to a template file when rendering a view, whereas rails' convention over configuration in this case relieves the user of a repetitive and non-interesting operation.
    The reason for this is philosophical - one of key ideas in Python is that "magic" is bad. It's far better to be explicit than to have code assuming things behind your back.
    Anyway there are plugins for rails that allow time based invalidation, and I believe that it should be possible to expire something in an event-based fashion in django too, cause the underlying mechanics are the same (CACHE.set(key,val), CACHE.get(key) and CACHE.del(key)).
    Yep, just write the appropriate code and hook it in where you want, or use a signal.
    It seems that django doesn't provide the fine-grained caching control that rails has, allowing just a whole-page caching or forcing the user to resort to the low level cache api, which I think is a bad thing.
    You can cache anything you want in Django - we provide high level caching shortcuts, but it's just as easy to cache, say, an object, or a chunk of rendered content etc using the low-level caching system. And by "low-level", we're jsut talking about: something = "I want to cache this string" cache.set('cachekey', something, time_period) I think you've got a typo in the globalisation section:
    First, django provides internationalization as a builtin concept while in django
    One of Django's strong points is i18n/l10n, so I think you meant to say "...while in rails..." Cheers, Simon G.
  4. riffraff Says:
    thanks for the comment. Yes, I understand the zen of python and that explicit is better than implicit, I'd just prefer if it behaved slightly differently, but it is just my preference not The Right Thing. I know you can cache anything you want in django, but I think that higher level behaviour should be provided, for example to cache just a part of the page in rails you can write: <% cache do %> <% for foo in baz %> <%= computationally_heavy_rendering %> <% end %> <% end %> which I think is quite nice, useful and is something that every user would benefit of if django provided it as a builtin. Oh, and I'll fix the typo thanks again :)
  5. Giovanni Corriga Says:
    Nice comparison, but now I demand a Seaside review ;)
  6. Thanh Ly Says:
    Adding to what Simon G. said about "explicitly point out to a template file when rendering a view": It's for the same reason Django makes you explicitly map URLs to your "action" or "view" however you want to look at it. Lets say you want to use the built-in Auth app. This quickly and easily provides your web app with login/logout. Now what do you suppose your URL will look like? /login and /logout right? Well your actions that invoke the login/logout methods of the Auth module can't be named "login" and "logout." In a framework that automatically makes the method become the URL, you might end up with something ugly like /site_login and /site_logout. With Django's URL mapping, you have have nice clean URLs even if it clashes with another method name in some module, your action's method name can be something wacky and your URL will still look pretty. This might not be the best thing to do, but this is how I'm taking advantage of the fact that Django makes you explicitly specify the template name when rendering: I have a submission form, if the user enters that page normally (no POST data yet) my action uses the template that has the html form in it. If there is POST data, the same action processes it and then renders a different template (the result of the submission).
  7. riffraff Says:
    sorry, but maybe I failed to express myself. I'm just saying that it would be nice to have some _defaults_, which do not rule out the option of specifying things explicitly, they just let you pay for what you pick and not for everything. Again, I know the zen of python, and I understand why this would not fit in django, it just does not match my personal preferences, which are not that important :)

Sorry, comments are closed for this article.