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