Second first impressions of Django

Posted by Jeremy Voorhis Thu, 18 Aug 2005 18:28:00 GMT

After completing the Django tutorial and tooling around with it, I got a better idea what it’s all about. Django’s big win is by far is its powerful dynamic admin. Look what I got for free!.

Ok. Not quite free – I had to add a little bit of code to my models, but this added up to about 4 or 5 lines. I quite envy Django’s many-to-many selector widget, and I’ve begun making one with Rails, but using drag’n’drop instead of the buttons. Nice thing about the buttons, though, is that you can highlight multiple items on the left (without holding ctrl) and select them all with one click. Nice. And that template in the screenshot is just waiting for me to override it with Django’s template language.

Another powerful thing in Django is the way it exploits the __repr__ method. Look at the screenshot again. It is not the best example, but you might get an idea of how adept Django can be in organizing data – if there were indeed multiple artists, the selector would group albums by artist, and then display the albums in chronological order. As you might guess, I could easily change that behaviour in one line. The __repr__ method of the Album model is what makes an album display itself as “Artist name: Album title” rather than just the album title.

Another nicety of Django is that certain field types have certain implicit behaviours. A meta.FileField will automatically render itself as a file upload field in the dynamic admin. But that’s not all – it also encapsulates the functionality to upload a file to the directory specified by the application’s MEDIA_PREFIX setting. The downside? I could not delete the file once it was uploaded. Optimistically, I filed a ticket requesting this functionality.

One of Django’s most controversial features is SQL generation. Initially, I found it worked quite well and there was no chance of my models being out of sync with the database. The pluggable applications manage their own tables, so when you drop an application into your Django project, you can run django-admin.py install <app> and you’re good to go. The big downfall? Change becomes cumbersome. Upon changing a model whose data is not expendable, you must alter the table manually. Otherwise, you may run django-admin.py sqlreset <app> and pipe the output into your database like so: django-admin.py sqlreset monkey | mysql -u root --database=monkey. Rick Bradley has posted a well-written article to the Rails mailing list that treats this subject in more depth. It is also available at his blog

Django also has what I would deem to be a major shortcoming in its template system – urls have to reference the prefix at which the application is installed. For example, in the tutorial the base url for the polls application is /polls. Templates within the polls application are required to be aware that they lived at /polls. This means if I wanted to install the application at another location, I would have to find and replace every instance of /polls in my templates. Rails solves this problem with its routing system, but routes can be difficult to use beyond a certain threshold of complexity. Django’s facilities for regular expression-based url design allow you to create urls of any complexity, but I have not yet seen a solution to decouple the templates from their urls.

As I expected, I have to clarify a few things from the last article. First of all, Django’s does have a capable equivalent of helpers – custom tags and filters. You can define custom tag libraries and include them in your project to accomplish similar sorts of tasks one would use helpers for in Rails. Another retraction: as Adrian commented in my first Django post, Django is hardly like Rails at all. In terms of its goals, it is more like OpenACS.

My experience Django was positive. I finally got around to learning Python, and I got to weigh for myself the benefits and pitfalls of Rails’ and Django’s techniques to implementing software patterns, such as object-relational mapping and URL routing. I can see how Django would be a good fit with the “newsroom environment” it was created for, and I left with the impression that Django is much more of a specialist than Rails. It does not strive to be an all things to all people framework, but rather an excellent starting point for implementing common website functionality.

Finally, another big win for Django is its active community. The guys in #django are very friendly and the lead developer is accessible, open-minded and willing to discuss things. Thanks, Jacob!

Comments

  1. RLivsey said about 2 hours later:

    I made a pretty fully featured multi-select list a while ago.

    http://livsey.org/experiments/multiselect/

    Simply give your select box a class of ‘multiselect’ and the javascript does the rest.

    I’m in the process of rewriting to use the prototype library, but it’s still good to use in its current state.

  2. Jeremy Voorhis said about 2 hours later:

    RLivsey,

    I like it. Add drag’n’drop and make it a gem!

    Unless I do first… I’m halfway there :)

  3. Adrian Holovaty said 1 day later:

    Thanks for your comments (and for your contributions on IRC and in the ticket system). Hope you stick around!

  4. Jeremy Voorhis said 1 day later:

    Adrian,

    As always, you’re very welcome. I firmly believe in the value of an outside perspective. That being said, Django has helped me think about web development in new ways.

  5. Derek Haynes said 1 day later:

    Thanks for the objective review! Having never touched Python, how much of a learning curve did you have with the language after using Ruby?

  6. Jeremy Voorhis said 1 day later:

    Python really wasn’t too hard to learn. I kept a PDF copy of Diving Into Python handy. Some things were new to me, like tuples, but they seem just like constant arrays with an extra comma.

    My impression of Python before ever using it was that it was a “dynamic Java”. After using it, that still doesn’t seem so far off.

  7. rick said 12 days later:

    Jeremy, regarding your beef with the URLs in the templating system, it looks like you can decouple them. It looks like you map the url to the app’s URL :

    (r’^weblog/’, include(‘django_website.apps.blog.urls.blog’)), (django_website/settings/urls/main.py)

    Then, the views in django_website/apps/blog/urls/blog.py assume you’re starting from that weblog directory.

    Course, you my have already figured this out since you posted this :)

Comments are disabled