Showing posts with label django. Show all posts
Showing posts with label django. Show all posts

Saturday, December 22, 2007

Django : First Impressions

In my last post, I spoke of my experience with Pylons, a Python rapid web application development framework similar to Ruby on Rails, and drew parallels with popular Java frameworks I have used in my development work. An anonymous commenter expressed surprise at one of my comments where I said I considered TurboGears and Pylons top contenders in this space, and pointed out that Django has more people on its mailing lists and a longer list of deployed sites in production.

First off, let me say that I am no expert in Python frameworks. I happen to like the Python language, and use it for all my scripting work. I use Java for web development, and I picked up PHP again when I built a small application recently. However, I have admired Ruby on Rails for a while, but was too lazy to learn the Ruby language, so I was really looking for something similar in Python-land.

So anyway, when I looked at Django the last time around, I thought it looked kind of (too) optimized for developing database driven web applications. Also both TurboGears and Pylons leverage external projects for part of their functionality, so as a Java programmer, that approach appeared more attractive to me. However, I realize that I may have been kind of hasty in my comment, so I decided to download Django and run through the tutorial (which is a database driven app, but at least I would know more about it than I did when I wrote the comment.

The installation was completely painless. I downloaded the tarball for the latest official release (0.96.1) from the site, then ran

python setup.py install
to install it. I then followed a very informative 4 page tutorial to build a poll system with a MySQL backend. This includes a very pretty and functional admin interface, along with the user facing application itself. I won't bore you with the details, except to say that the tutorials are quite extensive and very detailed, and all the commands work as advertised.

Running

django-admin.py startproject ${project_name}
creates an empty project template for you. The template is sparser than a Rails project, it consists of just 4 files in the project directory. The manage.py is the super-script (similar to the Rails scripts in the scripts directory) that you will use to generate and run almost everything, which delegates to the manage.py program in Django's installation.

To run the application for development, Django provides a runserver subcommand for manage.py (

python manage.py runserver
) which instantiates a HTTP server at port 8000.

Application wide configuration is through a single settings.py file. Sub-applications in the webserver are stored as subdirectories, which are accessed through Django code as Python packages. Each such package can have its own settings.py file for configuring that package. To create a package, run the command

python manage.py startapp ${packagename}
, this will create a subdirectory with the skeleton code for models.py and views.py.

Django follows the MVC paradigm, however, the nomenclature used is somewhat different. Database tables are mapped directly to models in models.py, and the controller methods are declared in views.py. The actual views are in a template directory that is defined in settings.py. The templates contain HTML and markup in Django's custom templating language. So the MVC is actually MTV in Django.

Django's custom ORM is quite lean, and similar to SQLAlchemy in Pylons, and like RoR, has support for declaring and following 1:1, 1:n, and n:n relationships. Each database table is modelled as a class in the models.py file in the package directory. One sets up the database mappings in the settings.py file, then creates the model classes. Then we need to run

python manage.py syncdb
to create the tables in the database. However, I found the SQLAlchemy API more intuitive.

I particularly liked the Django shell, in which it is possible to interactively play with the models, adding and removing data, to see if everything works. It can be started with

python manage.py shell
at the command line.

The templating language is custom to Django. It contains most of the simple control structures you would expect. However, the impression I got is that the preferred way is to do as much processing as possible in the controller layer (methods in views.py), which is what I would prefer to do in any case.

Overall, I liked Django. It is very similar to RoR, probably more so than TurboGears and Pylons, in the sense that it is a custom full-stack application optimized for database-driven apps. Django's routing appears to be slightly more advanced since regular expressions can be used to specify patterns, but clean URLs can be constructed by both frameworks. Pylons generates a nicer directory structure and uses (in my mind at least) correct nomenclature; however, that is probably just a function of usage.

From browsing the net, it seems that there is a stronger following for Django than for Pylons. Comparisons between TurboGears (and by extension, Pylons, which is very similar) and Django seem to favor the latter. However, there seems to be a dedicated following for Pylons as well. I found both Pylons and Django to be equally effective for my purposes, although I found Pylons to be more Java like, and thus more intuitive. Both offer functionality similar to RoR, which is great news for Ruby-challenged Python programmers like me.

And to the anonymous commenter, thanks very much for pointing me to Django.

Monday, December 17, 2007

First Steps with Pylons

I have written previously about how impressed I was with Ruby on Rails (RoR) when I first came across it about a year or so ago. For me, it represented a shift in the way web applications were designed - rather than build an individual application from scratch, the framework generates a template which can be extended as needed for the given application. Obviously, convention over configuration is an important aspect of this approach, since the template code will expect to find files with the "right" name and in the "right" location.

However, I did not know the Ruby scripting language, and in spite of my best efforts, I haven't been able to muster up enough interest to take the time and learn it. For one, Maven 2.x offers a similar (although not as complete) functionality to build application archetypes, and since I mostly do Java web application development for a living, it seemed a better investment of my time to work with Maven2 and Java. Second, although RoR seems to have impressive mindshare among the web literati, my personal experience is that customers expect a mid to large scale apps to be in Java. They usually don't have an opinion about smaller scale (3-10 page) apps, but I find PHP far simpler, more natural, and more than up to the task for building one of these. So there is not enough incentive for me to learn a language in order to use a framework that I will hardly ever use.

However, PHP uses the "code-in-page" approach, which is not easy to maintain once the application grows beyond a certain size. What I needed was a MVC framework based on a scripting language I already knew and enjoyed working in. Happily, when looking recently, I found not one, but three popular open source MVC frameworks based on Python - Django, TurboGears and Pylons.

Of these, TurboGears and Pylons are more glue-like, assembling the framework from a variety of other open source sub-frameworks. It is also possible to switch out some of the sub-frameworks and replace it with another if its a better fit for the application or the programming environment.

I started playing with TurboGears, since that is the more mature (and more stable, I hoped) framework of the two. Unfortunately, I could not get tg-admin to build my application template, because there were some modules mismatches with Python 2.5. After spending an afternoon trying to debug the problem, I gave up and tried Pylons. Installation was a breeze, partly because I already had some of the components installed for TurboGears, but there were absolutely no surprises, and everything worked as expected. I was able to get through the Getting Started (a Hello World style web application) and the Quick Wiki Tutorials within the next couple of days.

As I mentioned above, Pylons is composed of a number of sub-frameworks, each of which are independent projects in their own right. The Paster component provides commands to build an application template, similar to Maven2's archetype:create command, and to deploy the application as a Python egg (similar to WAR files in Java web applications). It also provides a built in HTTP webserver to test the application, similar to Maven2's Jetty plugin.

For database access, Pylons uses the SQLAlchemy project, which provides a Hibernate like API to access database tables and rows as Python objects. These are called model objects in Pylons. Each table (or logical group of tables) is modelled as a Python class. The SQLAlchemy engine is injected into the environment using a Python call in environment.py. The engine exposes a Session object, similar to Hibernate, from which a Query object is extracted. Method calls on the Query object translate to SQL queries to the database. However, the caller only sees application objects. This approach works great when the application gets to decide the database schema, but would probably be slightly more difficult (although not impossible) when building an application against an existing database. In this respect, it has the same limitations as Hibernate. I still need to delve deeper into this though.

For the page rendering subsystem, Pylons uses the Mako templating framework. Mako templates have markup that seems to be a superset of JSTL-style tags and something like Velocity-style tags. The JSTL style tags work off predefined model objects which are injected by Pylons controllers. Personally, I think its a bit confusing to have two kinds of markup, but I guess it may have just evolved that way. Although I am still new to Pylons, I think this would be one of the candidate subsystems where I may be tempted to look for alternatives.

The controller subsystem is provided by Pylons itself, and it is all straight generated Python code. There is a provided BaseController object which all application controllers must extend. The structure of an application controller seems to be similar in style to a Spring MultiActionController, with each public method mapped to a URL pattern, and representing a user action.

To route user URLs to the appropriate controller method, Pylons uses the Routes project. The default routes are set up an in-memory Python dictionary data structure. Additional application specific mappings are added to this structure using additional map.connect() calls in routing.py. This approach appears to be more powerful than Spring XML configuration, in that it allows regular expressions as well. TurboGears uses @expose annotations within the controller methods to do this, which may or may not be better depending on your point of view.

Thus, for a Java programmer who has worked with Maven2, Spring and Hibernate, getting started with Pylons is likely to be quite easy, probably more so than RoR. Of course, it would help if you already knew some Python. I think the relative popularity of RoR among Java programmers is because a lot of them would list Perl as their favorite scripting language, and Perl to Ruby is not that much of a stretch. Perl used to my favorite scripting language at one point, but ever since I began to use Python, reading and writing Perl code is less fun than it used to be. Python is very Java like in a lot of respects, although it is much more concise.

I think that another reason for the relative obscurity of Python based MVC frameworks is the availability of too many choices. Given that Python's philosophy is that "there should be one — and preferably only one — obvious way to do it", I can see how multiple frameworks could be anathema to Python programmers. However, jokes apart, this does dilute the focus of any serious efforts at popularizing a framework. Unlike RoR, there is no one "right" way to do rapid MVC development in Python. However, this is changing, and the two top contenders (in my opinion) in this space are TurboGears and Pylons. The two are very similar, although each glues together different sets of sub-projects. As Ian Bicking states:

I'd have a hard time describing the technical differences (between TurboGears and Pylons) in a meaningful way to someone who didn't already know something about Python web development.
However, TurboGears 2.x will be based on Pylons, so soon Python web developers will have one uber MVC framework to work with, possibly composed of the best sub-projects from either framework. Of course, in keeping with the "glue" philosophy, I expect that the programmer would be able to switch a component out with another one in the same category if required.