Files
pecan/docs/source/routing.rst
2011-03-11 00:22:30 -05:00

169 lines
4.7 KiB
ReStructuredText

.. _routing:
Routing
=======
When a user requests a Pecan-powered page how does Pecan know which controller to use? Pecan uses a method known as Object-dispatch to map a HTTP request to a controller. Obejct-dispatch begins by spliting the path into a list of components and then walking object path starting at the root controller. Let's look at a simple store application: ::
from pecan import expose
class BooksController(object):
@expose()
def index(self):
return "Welcome to book section."
@expose()
def bestsellers(self):
return "We have 5 books in the top 10."
class CatalogController(object):
@expose()
def index(self):
return "Welcome to the catalog."
books = BooksController()
class RootController(object):
@expose()
def index(self):
return "Welcome to store.example.com!"
@expose()
def hours(self):
return "Open 24/7 on the web."
catalog = CatalogController()
A request for ``/catalog/books/bestsellers`` from the online store would begin by Pecan breaking the request up into ``catalog``, ``books``, and ``bestsellers``. Next, Pecan would then lookup ``catalog`` on the root controller. Using the ``catalog`` object, Pecan would then lookup ``books`` followed by ``bestsellers``. What if the URL ends in a slash? Pecan will check for an ``index`` method on the current object. In the example above, you may have noticed the ``expose`` decorator.
Routing Algorithm
-----------------
``_lookup``
-----------
::
from pecan import expose
from mymodel import get_student_by_name
class StudentController(object):
def __init__(self, person):
self.student = student
@expose()
def name(self):
return self.student.name
class ClassController(object):
@expose()
def _lookup(self, name, *remainder):
student = get_student_by_name(name)
if student:
return StudentController(student, remainder)
else:
abort(404)
``_default``
------------
::
from pecan import expose
class RootController(object):
@expose()
def hello(self):
return 'hello'
@expose():
def bonjour(self):
return 'bonjour'
@expose():
def _default(self):
return 'I cannot say hi in that language'
``_route``
----------
::
from pecan import expose
Controller Args
---------------
::
from pecan import expose
class RootController(object):
@expose()
def say(self, msg):
return msg
Client requests ``/say/hi`` the controller returns "hi".
::
from pecan import expose
class RootController(object):
@expose():
def say(self, msg=None):
if msg is None:
return "I not sure what to say"
else:
return msg
Client requests ``/say?msg=hello`` the controller returns "hello".
Generic Functions
-----------------
::
from pecan import expose
class RootController(object):
@expose(generic=True)
def index(self):
pass
@index.when(method='POST'):
def index_post(self):
pass
@index.when(method='GET'):
def index_get(self):
pass
Helper Functions
----------------
redirect
abort
``@expose``
===========
At its core, ``expose`` is how you tell Pecan which methods in a class are controllers. ``expose`` accepts eight optional parameters some of which can impact routing. ::
def expose(template = None,
content_type = 'text/html',
schema = None,
json_schema = None,
variable_decode = False,
error_handler = None,
htmlfill = None,
generic = False):
Let's look at an example using template and content_type::
from pecan import decorators
class RootController(object):
@expose('json')
@expose('text_template.mako', content_type='text/plain')
@expose('html_template.mako')
def hello(self):
return {'msg': 'Hello!'}
You'll notice that we used three expose decorators. The first tells Pecan to serialize ``dict`` using JSON serialization when the client requests ``/hello.json``. The second tells the templating engine to use ``text_template.mako`` when the client request ``/hello.txt``. The third tells Pecan to use the html_template.mako when the client requests ``/hello.html``. If the client requests ``/hello``, Pecan will use the text/html template.
Advanced Routing
----------------
Hooks
Security
REST Controller