Files
pecan/docs/source/rest.rst
2011-04-18 11:56:54 -04:00

6.6 KiB

REST Controller

If you need to write controllers to interact with objects, using the RestController may help speed things up. It follows the Representational State Transfer Protocol, also known as REST, by routing the standard HTTP verbs of GET, POST, PUT, and DELETE to individual methods:

from pecan import expose
from pecan.rest import RestController

from mymodel import Book

class BooksController(RestController):

    @expose()
    def get(self, id):
        book = Book.get(id)
        if not book:
            abort(404)
        return book.title

URL Mapping

By default, the RestController routes as follows:

Method Description Example Method(s) / URL(s)
get_one Display one record. GET /books/1
get_all Display all records in a resource. GET /books/
get
A combo of get_one and get_all.

GET /books/

--------------------------------------------+

GET /books/1

new Display a page to create a new resource. GET /books/new
edit Display a page to edit an existing resource. GET /books/1/edit
post Create a new record. POST /books/
put
Update an existing record.

POST /books/1?_method=put

--------------------------------------------+

PUT /books/1

get_delete Display a delete confirmation page. GET /books/1/delete
delete
Delete an existing record.

POST /books/1?_method=delete

--------------------------------------------+

DELETE /books/1

Pecan's RestController uses the de-facto standard ?_method= query string hack to work around the lack of PUT/DELETE support in current browsers.

The RestController still supports the index, _default, and _lookup routing overrides. If you need to override _route, however, make sure to call RestController._route at the end of your custom _route method so that the REST routing described above still occurs.

Nesting

RestController instances can be nested so that child resources get the parameters necessary to look up parent resources. For example:

from pecan import expose
from pecan.rest import RestController

from mymodel import Author, Book

class BooksController(RestController):

    @expose()
    def get(self, author_id, id):
        author = Author.get(author_id)
        if not author_id:
            abort(404)
        book = author.get_book(id)
        if not book:
            abort(404)
        return book.title

class AuthorsController(RestController):

    books = BooksController()

    @expose()
    def get(self, id):
        author = Author.get(id)
        if not author:
            abort(404)
        return author.name

class RootController(object):

    authors = AuthorsController()

Accessing /authors/1/books/2 would call BooksController.get with an author_id of 1 and id of 2.

To determine which arguments are associated with the parent resource, Pecan looks at the get_one or get method signatures, in that order, in the parent controller. If the parent resource takes a variable number of arguments, Pecan will hand it everything up to the child resource controller name (e.g., books in the above example).

Custom Actions

In addition to the default methods defined above, you can add additional behaviors to a RestController by defining a special _custom_actions dictionary. For example:

from pecan import expose
from pecan.rest import RestController

from mymodel import Book

class BooksController(RestController):

    _custom_actions = {
        'checkout': ['POST']
    }

    @expose()
    def checkout(self, id):
        book = Book.get(id)
        if not book:
            abort(404)
        book.checkout()

Additional method names are the keys in the dictionary. The values are lists of valid HTTP verbs for those custom actions, including PUT and DELETE.