========================================== Tips for Writing Pylons Controller Actions ========================================== :Author: Mike Orr :Date: 2006-12-07 QuickWiki actions ================= 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. ``_(string)`` Translate the argument into the user's preferred language using the translation tables in ``quickwiki.i18n``. ``abort`` 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. ``c`` The "context" global. Used to pass data to the templates or between methods. ``cache`` @@MO Something related to Pylons caching. ``etag_cache`` Manages browser caching ("304 Not Modified"). See ``pylons.helpers.etags_cache`` for usage. ``g`` The "globals" global. You can assign attributes in ``quickwiki.config.app_globals`` and they will be initialized at the start of the application and remain alive for every request until the application shuts down; thus it's a good place for shared external resources. By default it has only one attribute ``.pylons_config``, the application configuration based on the config file that started it. ``h`` The "helpers" global, described in the "Helpers" section below. ``jsonify`` 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!"} ``model`` Same as ``quickwiki.models.__init__``. ``redirect_to`` Redirect the user to a different URL. This is the ``routes.util.redirect_to()`` function, which should be studied along with ``routes.util.url_for()`` for the usage and behavior. ``render(relative_template_path)`` Fill the specified template using data from the ``c`` global. This goes through ``pylons.templating``, which provides a unified front end to several template engines (Myghty, Cheetah, Kid, etc). ``render_response(relative_template_path)`` Convenience method to fill a template and wrap the result in a ``Response`` in one step. Useful if the default response options are appropriate. ``request`` A ``paste.wsgiwrappers.WSGIRequest`` with information about the request. Frequently-used attributes: .params MultiDict of POST/GET parameters. .environ The WSGI environment dict. .headers Dict of incoming HTTP headers. Includes only the CGI "HTTP\_\*" headers. Access as "request-method" or "REQUEST_METHOD" (case insensitive) *without* the "HTTP\_" prefix. .cookies Dict of incoming cookies. .host, .scheme, .script_name, .path_info URL parts. .method "GET" or "POST". .body The request body as a file-like object. Not usually necessary because ``.params`` processes POST vars for you. ``rest`` 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. ``Response`` You must return an instance of this. ``session`` A dict-like object that is persistent between requests during this browser session with this user. You can store anything in it. ``validate`` Decorator to validate input from a FormEncode schema or from individual validators. See ``pylons.decorators.__init__`` for usage and behavior. ``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``. Helpers ======= ``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: From pylons.util ---------------- 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``. From webhelpers --------------- See http://pylonshq.com/WebHelpers/. Seeing the global values ======================== 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.) .. include:: pylons-links.txt