Giving up on Ruby on Rails for Python and Django

24 02 2008

Well, a while back I wrote about starting to use Ruby on Rails to build myself a web application to track technical papers which I had read or planned to read. I gave up on RoR after a (very short) time period. Now, despite preferring to code in Ruby over Python, I’ve switched to Django. Why?

  • While I am capable of writing SQL myself, I really, really loathe it.
  • The Django documentation is easier to find/deal with
  • Django seems to do more busywork for you than Rails does.
  • It’s easy to poke around in the intermediate stages of development.

One of the pain points of RoR is the fact that you still have to deal directly with your database engine (likely, as in my case, MySQL). I’ve learned to deal with SQL after working on Mocha for a while. That doesn’t mean I like it. In fact, it’s still a pain. And the worst part of dealing with SQL is setting up tables, which is in fact the only database work Rails requires you to do – the worst part. It then does some magic to connect your ruby to the schema you’ve specified. Django lets you define the data model directly in Python. From there, it automatically creates the SQL tables, including creating join tables for many-to-many relationships, which is where I hit the main roadblock with Rails; I knew how to define the tables for the many-to-many relationship, but for whatever reason couldn’t easily find information on making a many-to-many relationship explicit in the Ruby model. The only SQL I had to do with Django was enough to create a new database, and ‘CREATE DATABASE whatever’ isn’t much to do, even if you’ve never used SQL directly before.

The many-to-many relationships documentation for Django is still a bit confusing, but clear enough that you can play with things, and unlike RoR, I could find it. The RoR documentation seems to consist primarily of the class API docs (only useful once you already mostly know what you’re doing) and somewhat mediocre 3rd-party tutorials. The Django documentation is actually organized as a manual. Overall the Django documentation is clear, and the initial tutorial on the Django site is incredibly useful – I’ve built everything thus far simply following along with the tutorial and tweaking things as needed – following links to more detailed documentation on what data types are available, using many-to-many instead of many-to-one, etc. Django also creates far fewer files, and almost all of them have an immediately obvious purpose. There’s less magic in the system, without making you do more work. It also makes setting up an administrative interface much easier, and includes a module for easy authentication setup for your application in the default install.

This is not to say that picking up Django has been nothing but butterflies and ponies; I’ve run into a few rough edges.

One design decision in Django that I’m not sure I’m happy with (though I’m not unhappy with it either) is the decision to orient it towards a “newsroom model” as the tutorial describes it. This means that the architecture was designed with the intention that there were distinct sets of users: publishers and readers. Django includes a big module (the one just mentioned above) for managing users and creating an administrative interface (‘django.contrib.admin’) and the documentation suggests its use. While you’re certainly free not to use it, its presence encourages its use, thereby encouraging the same model the developers had in mind. This isn’t necessarily a bad thing. I’m not sure it makes a difference to me, though it definitely encourages a split interface between the two sides of the application, which might not be right for all cases.

The real rough edges I’ve been rubbing up against are mostly regarding the many-to-many relationship. While I wasn’t expecting everything to be perfect, the disparity in easy flexibility between normal object fields and many-to-many fields is surprising. For example, the administrative interface Django suggests includes support for a lot of easy UI additions, such as searching on fields. This works great for standard fields, and not at all for many-to-many fields. In my case I have a many-to-many mapping relating papers and authors. For other fields in the Paper or Author models, I can add a search_fields = [‘title’] and make it easy to search the titles in the UI. Doing the same for the author list (a many-to-many field) does nothing. The semantics aren’t clear, but there doesn’t seem to be an easy way to add this functionality. The other issue is the manager class which is actually returned for member accesses to that field of the Paper object; it masquerades as a list, but isn’t one. It has an iterator, and can be used normally in that way, but most of the standard list uses don’t apply. In my case, I wanted to use string.join() to concatenate the author names in a listing. I can accumulate a string with a for loop, but that’s not the most natural or idiomatic way to express that action. Little things like that.

Please, if it seems like I’m doing something retarded, or missing some part of the documentation on Django’s many-to-many relations, please tell me. Also, as a final note, it’s probably worth mentioning that the version of Django in Debian and Ubuntu’s repositories is slightly older than the version the main tutorial is for. I followed a link from that tutorial to the tutorial for the previous release.

Advertisements

Actions

Information

8 responses

24 02 2008
Barry

You should have looked at Rails Migrations. You code in pure Ruby, and the database tables get created for you. And the best part is that even if you decide to change database back-ends, your migrations stay the same. No need to touch SQL when working in Rails.

The other nice things about migrations is that you can “migrate” your database to any version you like. Made a change that stuffed up your production server? No problem. Just roll back to last known stable database version.

Rails manages all that for you.

24 02 2008
Barry

Oh yes, and the many-to-many relationships are handled by Active Record quite seamlessly. Just specify
has_and_belongs_to_many
in your models.

25 02 2008
Russell Keith-Magee

The list/iterator distinction isn’t a Django specific thing – it’s a fairly common Python idiom. In the simple case, you can always turn an interator into a list using list() (if x is an iterator, list(x) is a rolled out list containing everything in the iterator), but this isn’t normally necessary. Python’s list comprehension syntax:

For example:
‘:’.join(u.username for u in User.objects.all())

will return a string containing all the usernames in the database, separated bycolons. The “f(x) for x in iterator/list” syntax is called a list comprehension: it evaluates on-demand, so a temporary list isn’t required, and works on both iterators and lists.

Regarding the admin interface – contrib.admin is intended as a simple admin interface, not the be-all-and-end-all admin application. However, you can do searches across many to many tables. The double underscore syntax allows searches to traverse tables. For example, the Django query:

>>> Author.objects.filter(book__name__icontains=’foo’)

will traverse the book relation to search the name field of related books, and return Authors that match. This query is exactly equivalent to specifying search_fields = [‘book__name’] in the Admin class of Author.

25 02 2008
Robert Brewer

Actually, Russell, that’s a “generator expression” you’ve got there. A true “list comprehension” uses [square brackets] instead of parentheses and *is* evaluated immediately, creating an intermediate list which the join then acts upon. See http://docs.python.org/ref/lists.html.

19 07 2008
AD

You are way absolutely right that Django’s documentation is easy and up to date. Even the rails official site does not point to updated documentation. Thats what makes Django a good choice for beginners.

17 12 2008
Ricardo A. Salgado

Another issue i found in rails running on Windows XP is that version 2.x does not generate complete code from tables using the “script generate/scaffold SomeModel”, but prior versions do.

24 04 2009
Joshua

I must agree with you. Django is superb and do alot of dirty work. And most of all, I really appreciate how django developers are really humble and open to be schooled.

16 06 2013
garden

I blog frequently and I genuinely appreciate your information.
The article has really peaked my interest. I am going to
book mark your blog and keep checking for new details about once
per week. I subscribed to your RSS feed as well.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: