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.html 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:

<!-- End of main_content -->
<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('wiki20.templates.edit')
def edit(self, pagename):
    page = Page.query.get(pagename)
    return dict(page=page)

@expose("wiki20.templates.pagelist")
def pagelist(self):
    pages = [value[0] for value in
        Page.query.order_by(Page.pagename).values(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). We’re selecting all of the pagenames here, ordered by pagename. The result is a sequence where every row is a tuple with just one element, the pagename. We convert this sequence into a list of pagenames 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 page 6