or “Refactoring a tiny web app in 2 hours”
Last fall I wrote a little web app (less than 500 lines) that ran on the wsgi_ref server that comes with Python.
Yes, I know wsgi_ref isn’t exactly intended for production apps, but I had my reasons. First of all, it was a very bare-bones report extractor/generator aimed at fewer than half a dozen users and I didn’t want to mess with any third party libraries, installation, configuration, etc. Also, after using wsgi_ref in some examples in The Quick Python Book, I was curious as to how useful it might be in a real situation.
It worked okay, and the people concerned were quite happy with their new web-based report extraction system. Of course, as often happens, the more I thought about it (and maintained the code), the less happy I was.
For one thing, the code was a little ugly… well, as I think about it, given it’s small size, it was a LOT ugly. URL’s had be mapped to code explicitly, and the the whole thing was no where near as modular nor as readable as it should have been.
So as I thought about refactoring the app, I decided to see how much work it would be to swap wsgi_ref for CherryPy. I’ve always had a soft spot in my heart for CherryPy – I used it for my very first web app some 7 or 8 years ago, and at PyCon 2009 my sprint time was spent on the very early stages of converting it to Python 3.x.
And as it happened my thoughts of refactoring pretty much coincided with Bob Brewer’s talk about “The Zen of CherryPy” at PyCon 2010. I recommend watching the video of his talk when you have the chance, but I’ll give you the first two points – “Common tasks should be fast and easy” and “Doing nothing should be faster and easier”. That matched my app perfectly, since, as Yogi might have said, 90% of my app was doing common tasks, and the other 90% was doing nothing.
So I was looking for three things: first, how easy is it to port an app from the wsgi_ref server to a server like CherryPy? and second, would it help me improve my code? and finally, does CherryPy follow the “Zen” as Bob presented it? Or to put all three in another way, is it worth the effort to use a server package like CherryPy for such a tiny web app?
Shortly after lunch on Friday (March 19) I grabbed CherryPy and installed it on our vTiger server. Following the tutorial, I shortly had a little demo app working. The next step was to move my main web code into a class. After that, each one of the if statements explicitly mapping a URL was recast as an appropriately named method.
Fortunately, I was smart enough to put the code that actually queries the database and massages the data into the desired report into a separate module, so it remained untouched. After adjusting some parameters and making sure things were correctly exposed, the main report URL’s were working fine.
I had one entry form, and its HTML template needed a few tweaks. Reading the values from the form post (a common task) was dead easy – they just became parameters to the form action method. I also needed to change the response headers in one method to send a PDF instead of HTML, and that was a simple dictionary access of cherrypy.response. Again, a common task, easily done.
Finally, I needed to adjust the port number and make a couple of other minor changes to the configuration – a quick call to cherrypy.config.update took care of that. As to things like sessions, authentication, compression, etc, I didn’t want them, so I didn’t do anything. Doing nothing to do nothing works for me.
As to the answers to my questions, let me put it this way – my code is now much more modular and readable, and I got the whole refactoring done in time to make a three o’clock appointment.
CherryPy. Definitely worth it.