Today I implemented so-called ‘pretty urls’ for my Google App Engine application. While my URL structure was reasonably clean before this work, I was inspired to make improvements after attending ThinkVisibility and particularly after talks by Rob Lee and Tom Smith. While it wasn’t too painful to track down information on how I might achieve Pretty URLs in GAE, it did take a little trial and error to get running, so I thought it worth a post. Indeed, if readers have suggestions for a more elegant solution, I welcome comments.
What is a Pretty URL? A Pretty URL is a URL designed to be ‘hackable’, or human-readable. Ideally, users should be able to intuit a Pretty URL address, and likewise a Pretty URL might serve as a ‘bread crumb’ or ‘sign post’ indicating to the user where s/he is in the application. Compare, for example, a less than fetching URL (a) with a more pleasing example (b):
a) mysite.com/mycategory?myparam=an_entity_id
b) mysite.com/mycategory/an_entity_id
Example ‘b’ is just the sort of URL I desired; purdy, ain’t she?
I chose to use my WSGIApplication’s constructor to point Pretty URLs at appropriate Handlers:
application = webapp.WSGIApplication([('/category/.*', CategoryHandler)], debug=True)
The ‘category’ is associated with a particular Handler, while the ‘.*’ regex matches the UID of the entity to be retrieved, which is passed on the URL. In the Handler’s get function I retrieve the path instance variable include on the Request object, which returns a substring of the URL between the host name and query parameters. I then substring the path string in order to retrieve the key of the entity requested by the user:
path = str(self.request.path)
key = path[6:len(path)]
if key:
#Retrieve the entity and shoot back a response
This appears to be working well and as expected; I’m certainly blushing every time I lay eyes on one of my app’s sweet little URLs.
(Readers may wish to view Google’s doc on URL config; note if you try copying and pasting the syntax in their example you’ll get exceptions, hence the trial and error aspect of my implementation.)