Over the past week, I have been exploring Django, a Python-based web framework. My initial impression is that it is a very elegant system.
Like most web frameworks, Django is based on the Model-View-Controller (MVC) design pattern. In MVC, the model is the core data and process logic of the system. A view is a particular presentation of the model. There can be more than one view of the same model, and the two are kept as decoupled as possible in code. The MVC model originally came out of Smalltalk and user interface design. Under this original definition, a controller is the means by which the user interacts with the system, thus affecting the model and the corresponding view. Over time, the controller has come to refer more generally to the programming logic that glues together the views and the model. The differences between these diverse conceptions of the controller can make MVC seem confusing at first.
Regardless of the precise meaning of MVC, Django certainly does a good job separating the model and the various views of that model. The model is defined using an object-relational mapper. Essentially, each row (tuple) of a database table can be represented as an object. The columns of the table correspond to the object's fields. In Django, you define the classes for the objects you need, and Django then handles the necessary database table definitions. As a programmer with only some database experience, I found this a very comfortable approach. It also means that, since the database is dependent on the Django-defined model, you don't have to really touch the DB at all, even if you later change the model. This linked dependency is an example of Django's "Don't Repeat Yourself" (DRY) design philosophy at work.
Similarly, Django's template system makes views particularly easy to construct. Using a template, you define the HTML of a page and then embed the code snippets necessary to pull the required data from the model. You can even inherit one template from another. That is, you can define a general base page format, including where different subsections might go, and then separately customize the format of those multiple possible subsections. Again, this is the DRY principle at work.
Aside from defining the model and views, Django dynamically maps URLs to views. That is, you don't actually have a file hierarchy to manage or sets of files with technology-specific file extensions. Pages (views) are all generated dynamically, so the specific URLs of those pages can be customized from within a single script.
Aside from not having to repeat yourself, Django will do a lot for you "auto-magically". For example, it comes with a robust automatically generated admin user interface from which you can update content in the model. While all the necessary web forms are generated for you, you can also customize the details if necessary. This seems to be a common theme with Django: a smart default setting with the ability to modify it if necessary.
To offset the possible performance hit of generating pages for each request, Django has a page-caching system. It also has a syndication (RSS) system that I haven't explored.
In the past, I have used CGI to generate dynamic web content using either Python or Perl scripts. My experiences with Django so far have effectively overcome all the annoyances of the CGI approach. First, CGI scripts are usually stored in a cgi-bin while other static HTML files are elsewhere in the file system. This makes for some gnarly URLs, and any relative references between pages usually break if you try to restructure the site. Unlike Django's fairly clean template system, the program logic and page generation code are often fairly tightly intertwined in a CGI script, though you can factor out commonly shared page-generation code like page headers and footers. For any database support with CGI, you have to set up the database yourself and handle the specific calls yourself from the script. To avoid that logistical overhead, I have often favored storing data in flat text files instead, especially for small or simple CGI tasks. Django handles all of these details for you. The default Sqlite database is effectively a single file anyway, but it has the advantage of letting you scale up later if you decide you need a more robust DB backend.
Given my experiences so far, next time I need to generate more than the most trivial of dynamic web content, I'll definitely reach for Django first over using CGI.