20 Minute Wiki Page 5

Adding a page list

Our wiki is functional, but we’ll add a few more features to make it nicer and because we have more TurboGears features to demo.

Most wikis have a feature that lets you view an index of the pages. We can add that to our wiki easily, so let’s do it!

We’ll start with a new template, pagelist.html. Again, we’ll start with page.html so that we don’t have to write the boilerplate.

cd wiki20/templates
cp page.html pagelist.html
cd ../..

Our pagelist.kid will look like:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:py="http://genshi.edgewall.org/"
  xmlns:xi="http://www.w3.org/2001/XInclude">

<xi:include href="master.html" />

<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"
      py:replace="''"/>
<title> Page Listing - 20 Minute Wiki</title>
</head>
<body>
    <div id="main_content">
        <h1>All Of Your Pages</h1>
        <ul>
            <li py:for="pagename in pages">
            <a href="${tg.url('/' + pagename)}"
                py:content="pagename">Page Name Here.</a>
            </li>
        </ul>
    </div>
</body>
</html>

Feel free to add “Are Belong To Us” to the heading, if you feel you must.

Just as with the other templates, you can open pagelist.html directly in a browser. You can see that we’ll get a bulleted list of links to the pages. This is our first use of py:for, and you can see it’s straightforward. The li element will be repeated for each iteration of the for loop, and the for loop is specified just as it is in Python.

Let’s add a link at the bottom of the master.html template so that we’ll get our page listing link at the bottom of every page:

<div id="footer">
  <p>View the <a href="${tg.url('/pagelist')}">complete list of pages.</a></p>
  <div class="flogo">
    ...
  </div>
  <div class="foottext">
     ...
  </div>
</div>

Since we’re referring to a pagelist method, we should probably create it:

@expose(template="wiki20.templates.edit")
def edit(self, pagename):
    page = Page.get_by(pagename=pagename)
    return dict(page=page)

@expose("wiki20.templates.pagelist")
def pagelist(self):
    pages = [page.pagename for page in Page.query.order_by(Page.pagename)]
    return dict(pages=pages)

@expose()
def save(self, pagename, data, submit):
    #...

Now you see that this page listing is just a contrived reason to introduce you to SQLAlchemy’s querying facilities (tricky aren’t we). This particular use of Page.query isn’t particularly fancy. We’re selecting all of the Page objects from the database, and ordering them by pagename. Page.query returns an iterable Query object, which allows us to snag the titles via list comprehension. The query attribute attached to your object classes provides methods to construct almost any query you’d like to run on them. Check the sqlalchemy docs for more details.

You can see your pagelist by clicking the link at the bottom of your pages or going directly to http://localhost:8080/pagelist.

Go back to Page 4 | Continue on to page 6