4.8 KiB
Routing
Note
This portion of the documentation is still a work in progress.
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 splitting 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
Example :
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
Example :
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'
Overriding _route
Example :
from pecan import expose
Controller Args
Example :
from pecan import expose
class RootController(object):
@expose()
def say(self, msg):
return msg
Client requests /say/hi
the controller returns "hi".
kwargs :
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
Example :
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