Adding Wiki Pages

Controller

Controllers are the code that figures out which page to display, what data to grab from the model, how to process it, and finally hands off that processed data to a template.

quickstart has already created some basic controller code for us at wiki20/controllers/root.py. Here’s what it looks like now:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
"""Main Controller"""
from wiki20.lib.base import BaseController
from tg import expose, flash, require, url, request, redirect
from pylons.i18n import ugettext as _, lazy_ugettext as l_
#from tg import redirect, validate
from wiki20.model import DBSession, metadata
from wiki20.controllers.error import ErrorController

class RootController(BaseController):
    error = ErrorController()

    @expose('wiki20.templates.index')
    def index(self):
        return dict(page='index')

    @expose('wiki20.templates.about')
    def about(self):
        return dict(page='about')

8: We must import the Page class from our model. At the end of the import block, add the line:

from wiki20.model.page import Page

12: Change @expose('wiki20.templates.index') to:

@expose('wiki20.templates.page')

so that the data returned by the index controller will now be rendered by wiki20/templates/page.html. This requires us to create a new template named page.html in the wiki20/templates directory; we’ll do this in the next section.

13: We add a parameter to the index() method to specify the particular page we want to see by changing def index(self): to:

def index(self, pagename="FrontPage"):

This tells the index() method to accept a parameter called pagename with a default value of "FrontPage".

14: Now let’s get that page from our data model. Put this line in the body of index:

page = DBSession.query(Page).filter_by(pagename=pagename).one()

This line asks the SQLAlchemy database session object to run a query for records of the page table with pagename column equal to the value of the pagename parameter passed to our controller method. A .query call generally returns a list of matching objects. We only want one page, so we add the .one() method to assure only one returned result.

15: Finally, we need to return a dictionary containing the page we just looked up. When we say:

return dict(wikipage=page)

the returned dict will create a template variable called wikipage that will evaluate to the page object that we looked up.

Here’s the whole file after incorporating the above modifications:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
"""Main Controller"""
from wiki20.lib.base import BaseController
from tg import expose, flash, require, url, request, redirect
from pylons.i18n import ugettext as _, lazy_ugettext as l_
#from tg import redirect, validate
from wiki20.model import DBSession, metadata
from wiki20.controllers.error import ErrorController
from wiki20.model.page import Page

class RootController(BaseController):
    error = ErrorController()

    @expose('wiki20.templates.page')
    def index(self, pagename="FrontPage"):
        page = DBSession.query(Page).filter_by(pagename=pagename).one()
        return dict(wikipage=page)

    @expose('wiki20.templates.about')
    def about(self):
        return dict(page='about')

Now our index() method fetches a record from the database (creating an instance of our mapped Page class along the way), and returns it to the template within a dictionary.

View (Template)

quickstart created some html templates for us in the wiki20/templates directory: master.html and index.html. Back in our simple controller, the quickstart-generate code used @expose() to hand off a dictionary of data to a template called 'wiki20.templates.index', corresponding to the file wiki20/templates/index.html.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<!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>Welcome to TurboGears 2.0, standing on the 
  shoulders of giants, since 2007</title>
</head>

<body>
    ${sidebar_top()}
  <div id="getting_started">
    <h2>Presentation</h2>
    <p>TurboGears 2 is rapid web application development toolkit designed to make your life easier.</p>
    <ol id="getting_started_steps">
      <li class="getting_started">
        <h3>Code your data model</h3>
        <p> Design your data model, Create the database, and Add some bootstrap data.</p>
      </li>
      <li class="getting_started">
        <h3>Design your URL architecture</h3>
        <p> Decide your URLs, Program your controller methods, Design your 
		templates, and place some static files (CSS and/or JavaScript). </p>
      </li>
      <li class="getting_started">
        <h3>Distribute your app</h3>
        <p> Test your source, Generate project documents, Build a distribution.</p>
      </li>
    </ol>
  </div>
  <div class="clearingdiv" />
  <div class="notice"> Thank you for choosing TurboGears. 
  </div>
</body>
</html>

Copy the contents of index.html into a new file called page.html in the same directory.

$ cd wiki20/templates
$ cp index.html page.html

Now modify it for our purposes:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!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>${wikipage.pagename} - The TurboGears 2 Wiki</title>
</head>

<body>
  <div class="main_content">
     <div style="float:right; width: 10em;"> Viewing
        <span py:replace="wikipage.pagename">Page Name Goes Here</span>
        <br/>
        You can return to the <a href="/">FrontPage</a>.
  </div>
  <div py:replace="wikipage.data">Page text goes here.</div>
     <a href="/edit/${wikipage.pagename}">Edit this page</a>
  </div>
</body>
</html>

This is a basic XHTML page with three substitutions:

11: in the <title> tag, we substitute the name of the page, using the pagename value of page. (Remember, wikipage is an instance of our mapped Page class, which was passed in a dictionary by our controller.)

17 in the second <div> element, we substitute the page name again with Genshi’s py:replace:

<span py:replace="wikipage.pagename">Page Name Goes Here</span>

21: In the third <div>, we put in the contents of our wikipage:

<div py:replace="wikipage.data">Page text goes here.</div>

When you refresh the output web page you should see “initial data” displayed on the page.

Table Of Contents

Previous topic

Wiki Model

Next topic

Editing pages

This Page