TurboGears: 20 Minute Wiki, Page 4

## Friendlier URLs

Something that bothers me about the current setup is that the URLs are not as nice as they could be. Rather than "/?pagename=Foo", wouldn't "/Foo" be nicer? Luckily, this is really easy to do. We just add a default method that CherryPy will call whenever no other method matches:

<![CDATA[ @turbogears.expose(html="wiki20.templates.page") def default(self, pagename): return self.index(pagename) ]]>

And now, we can change the HTTPRedirect in the save method to turbogears.url("/%s" % pagename).

## What about WikiWords?

WikiWords have also been described as WordsSmashedTogether. A typical wiki will automatically create links for these words when it finds them. Sounds like a good idea, and this sounds like a job for a regular expression. Start by adding an import to our controller:

    import re

A WikiWord is a word that starts with an uppercase letter, has a collection of lowercase letters and numbers followed by another uppercase letter and more letters and numbers. Here's a regular expression that meets that requirement:

    wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)")

Put that line just above the Root controller class. Then, we need to use this regex. Just below the publish_parts line of the index method (that's the one that generates the HTML), add this:

Go ahead and edit your front page to include a WikiWord. When the page is displayed, you'll see that it's now a link. You probably won't be surprised to find that clicking that link produces an error.

## Hey, where's the page?

It's time to add a check for pages that don't exist. I'll keep the approach here simple: if the page doesn't exist, you get an edit page to use to create it. In the index method, we'll check to see if the page exists. If it doesn't, we'll redirect to a new notfound method. Change the index method like this:

<![CDATA[ try: page = Page.byPagename(pagename) except SQLObjectNotFound: raise cherrypy.HTTPRedirect(turbogears.url("/notfound", pagename= pagename)) ]]>

We'll need to import the exception as well. Add this to the top of the file:

<![CDATA[ from sqlobject import SQLObjectNotFound ]]>

And, we'll add the not found method. We'll just reuse the edit template.

<![CDATA[ @turbogears.expose(html="wiki20.templates.edit") def notfound(self, pagename): return dict(pagename=pagename, data="", new=True) ]]>

Notice that the dictionary includes a variable called "new" for use in the template. Change the edit method to set new=False when it returns its dictionary:

            return dict(pagename=page.pagename, data=page.data, new=False)

We need to be able to save a new item, so, we'll have to change the save method like this:

<![CDATA[ @turbogears.expose() def save(self, pagename, data, submit, new): hub.begin() if new == "True": page = Page(pagename=pagename, data=data) else: page = Page.byPagename(pagename) page.data = data hub.commit() hub.end() turbogears.flash("Changes saved!") raise cherrypy.HTTPRedirect(turbogears.url("/%s" % pagename)) ]]>

As we saw when we created the original FrontPage via the shell, instantiating an SQLObject is enough to INSERT into the database.

The one last thing we need to do is pass along the "new" variable to the save method via the form in edit.kid:

Give it a try! You should be able to create new pages now.

Continue on to page 5