12 Sep 2005
(updated 12 Sep 2005 at 20:58 UTC) »
While I was at my parents' farm last weekend I saw my mother taking a post-it note off of a box of fruit and sticking it in a big plastic tray. Turns out she's been labeling each box of fruit that goes into the walk-in cooler with type of fruit and when it was picked. As the boxes get emptied, she saves the labels so she can figure out how many boxes of fruit were picked at the end of the year.
Being the computer geek that I am, I said, "Let me put those in a database for you!"
Now my parents are willing to try all sorts of things on a computer but in the end they just want things to work the way they expect. So what I wanted in the design of this application was something I could design and implement under Linux that they could use and view from their Windows computer at home. My plan was to create and fill the database on my end and design a small web front-end for my parents to generate and print reports from their house.
This would also give me an opportunity to take a look at some of the Python-based web frameworks that have entered Fedora. mod_python's psp from Fedora Core; Quixote and cherrypy from Fedora Extras. After a few days of trying out examples from all three frameworks I came to some tentative conclusions:
psp is a direct competitor for php. It is the simplest to setup on Fedora Core as it is a simple matter of uncommenting some code in the mod_python config file. The mixing of html (where whitespace barely ever matters) and python (where it most definitely does) is worked out pretty logically, but viewing the code still proves jarring. Just using mod_python's req.write() method makes things look more like a python program but doesn't make reading the html any easier. Like php, psp doesn't take a definite stance on separating the processing portion of a program from the GUI portion. This makes it very easy to write poor code... but also seems to make quick, one-page scripts a distinct possibility.
cherrypy does not integrate with Apache (in cherrypy's current stable version). It sets up its own webserver which handles requests for the documents. You can configure Apache to redirect requests to the cherrypy server if you want Apache to handle static pages/virtual domains/etc but the cherrypy server still has to run in the background to handle the requests. cherrypy does not include its own templating language (there is a recommended add-on for this but it's not necessary). cherrypy got some rave reviews from the PyWebOff as a quick easy way to get an Internet application built. Looking over cherrypy's docs, the framework's model seems to be mapping python objects to URLs. In many ways it looks like cherrypy could be a standout framework for a web programmer. Unfortunately it doesn't fill any of the requirements I have for (the initial stages, at least) this particular application. I need a templating system that is better than php and about as easy to use. This is a web framework without templating that doesn't leverage any of my previous Apache knowledge. Perhaps at a later stage in polishing this application I'll look at porting the overall architecture to cherrypy but for now it's solving different problems than I need.
quixote integrates with Apache or runs standalone. The documentation on how to do this is somewhat sparse. There are examples of most things but figuring out how to adapt those to your needs isn't always clear. I spent quite some time trying to figure out if I could enable a quixote application from a .htaccess file or .psp driver script in case I ever needed to use this on a hosted server where I didn't have access to apache's configuration. This led down several promising alleys but never quite clicked. So I never truly got to play with the application framework inside of Quixote. From the documentation and tutorials it looks like it shares the cherrypy metaphor of mapping URLs to objects in python. However, it looks more procedurally oriented, mapping functions rather than objects.
The real find, however, was Quixote's templating language, PTL (Python Template Language). Until I saw this, I didn't know what I was missing. Conceptually a PTL template is a python function wherein every expression within it becomes part of the return value of the function. So this template:
def hello [html](name):
closing = "
""" % (name,)
will return a simple html page that does what you expect. The [html] type template even quotes any html reserved characters (such as &, >, <) inside of variables for you so there's less chance that user supplied input can insert malicious html into your web page. To me, this format is much more readable than any of the asp/php code-within-html-style languages.
After a bit of experimentation I was able to get this portion of quixote to work from within mod_python. I started with an index.psp driver file that had no html in it, just the code to enable PTL and load things:
from quixote import enable_ptl
# Enable loading modules in the script's directory
# Enable ptl
# ptl templates. common.ptl and front.ptl resp.
header = common.Header(title='Orchard Database')
footer = common.Footer()
page = front.FrontPage()
# And a mod_python call to output the page
# Note: Must format header/page/footer as strings as the raw objects are not
# strings. Instead they contain an __str__() function that returns the page as
# html. This could theoretically allow us to use the objects for output to something
# other than a webpage in the future.
req.write("%s %s %s" % (header, page, footer)
The nice thing about this is that I was able to get it up and running quickly. No messing around with Apache configurations since mod_python was already installed. Standard python-style hacking to define objects for pages/subsets of pages, meta-pages, etc. There are some drawbacks, though:
1) As I generate more pages, I find I'm reinventing some of the functionality present in the frameworks (quixote or cherrypy) in order to map URLs to my python page-objects.
2) mod_python byte-compiles the imported python files and then uses that in subsequent calls to that mod_python thread regardless of whether the *.py/*.ptl has changed. While developing and fixing bugs in the code, this quickly becomes annoying as I've been having to restart apache to get mod_python reloaded.
So PTL + mod_python looks like it was good to get me started quickly on this project but it's going to be PTL + one of the frameworks that I end up experimenting with for bigger things.