| Author: | Mike Orr |
|---|---|
| Date: | 2006-12-07 |
Here's quickwiki.controllers.page from the QuickWiki tutorial:
from quickwiki.lib.base import *
from quickwiki.lib.database import session_context
class PageController(BaseController):
def index(self, title):
page = self.query.get_by(title=title)
if page:
c.content = page.get_wiki_content()
return render_response('/page.myt')
elif model.wikiwords.match(title):
return render_response('/new_page.myt')
abort(404)
def __before__(self):
# This sets a SQLAlchemy *database* session, not a Web session.
self.session = session_context.current
self.query = self.session.query(model.Page)
def edit(self, title):
page = self.query.get_by(title=title)
if page:
c.content = page.content
return render_response('/edit.myt')
def save(self, title):
page = self.query.get_by(title=title)
if not page:
page = model.Page()
self.session.save(page)
page.title = title
page.content = request.params['content']
c.title = page.title
c.content = page.get_wiki_content()
c.message = 'Successfully saved'
self.session.flush()
return render_response('/page.myt')
def list(self):
c.titles = [page.title for page in self.query.select()]
return render_response('/titles.myt')
def delete(self):
title = request.params['id'][5:]
page = self.query.get_by(title=title)
self.session.delete(page)
self.session.flush()
c.titles = self.query.select()
return render_response('/list.myt', fragment=True)
Controller methods ("actions") are tied to URLs by the Routes routing map, as described in Pylons Execution Analysis. In that article we clicked on "TitleList" in our Web browser and went to URL "/page/list", producing these routing variables:
{'action': 'list', 'controller': 'page', 'title': 'FrontPage'}
We see this method sets a c attribute and calls render_response('/titles.myt'). c is a special global used to pass data to the template or between methods; essentially a miscellaneous container for the request. render_response() fills in the template and returns a pylons.Response object.
The "from quickwiki.lib import *" line makes lots of goodies available. These are specific to the current request.
Abort the request immediately and raise an HTTPException. Usage:
abort(404)
You can raise an exception from paste.httpexceptions yourself, or see paste.httpexceptions.abort() for additional features.
Decorator to convert a return value to JSON and wrap it in a Reponse with "Content-Type: text/javascript". Usage:
@jsonify
def my_controller_action(self):
return {"variable_for_browser": "JSONify me!"}
A paste.wsgiwrappers.WSGIRequest with information about the request. Frequently-used attributes:
Functions for REST-ful applications. This is the pylons.decorators.rest module.
- restrict
Decorator to restrict access to certain HTTP methods. The user will get a 405 error otherwise. Usage:
@rest.restrict("POST") def my_post_action(self): ...- dispatch_to
Decorator to switch to a different action based on the HTTP method. If the HTTP method does not match any of the keyword args, continue with the original action. Usage:
@rest.dispatch_on(POST="create_comment") def comment(self): # Display the comment. def create_comment(self): # Create the comment.
c, g, h, and pylons.request are special globals containing information about the current request and the server environment. c is the "context" object, used to pass data to the template or between methods. Initially it contains some of the routing variables:
print vars(c._current_obj())
{'titles': [u'Front Page']}
g is the "global" object. By default it has one attribute .pylons_config containing the configuration. You can add other attributes -- anything that's initialized at application startup and remains active through all requests -- in quickwiki.lib.app_globals.
h is the quickwiki.lib.helpers module. It contains generic functions useful in Web applications, including all the WebHelpers ported from Ruby on Rails. Here are some of the more interesting ones included by default:
- log
- Log a message to the server's error log.
- set_lang
- Set the user's preferred language.
- _
- Translate the given string into the preferred language using the gettext translations you've put in quickwiki.i18n.
To see what the global variables c, g, and h contain during each request, change quickwiki.lib.base.BaseController.__call__() to:
#return WSGIController.__call__(self, environ, start_response) print environ["pylons.routes_dict"] result = WSGIController.__call__(self, environ, start_response) import pprint print "c is", pprint.pformat(vars(c._current_obj())) print "g is", pprint.pformat(vars(g._current_obj())) print "g.pylons_config is", pprint.pformat(vars(g.pylons_config)) print "h dir is", dir(h) return result
You will probably want to quickly comment out some of these lines because the output is pretty verbose. (c and g are actually proxy objects, so attribute access is implicitly passed down to the real object but less common operations like vars() require the ._current_obj() call.)