On Dec 11, 2005, at 11:24 AM, reflog wrote:


Hi there.
I've been breaking my head trying to implement a nested urls thingie,
like:
site.com/pages/32/add
where pages would be a result of select, and 32 would link to a
controller of pages.

I tried to do the same thing and came up with this code (as a modification of the cherrypy recipie found at < http:// www.cherrypy.org/wiki/RestfulResource >).

Essentially, all you need to do is inherit from resource.Resource and define your own methods that take the 'object' from your model as the first argument... so, something like:
    http://site.com/pages/32/add

would map to:
    def add(self, obj):
        # where 'obj' here is the actual
        # sqlobject instance where ID=32

Also, if 'add' is a POST-able resource, then you can do what I've done below in the Pages.add method...

(to the list at large) Could we add the resource class as a utility class in the turbogears distribution (if someone hasn't already done something similar)? I remember reading on this list, though, that CherryPy 2.2 might have something like that by default. Is that correct?

--Tracy

#
# controllers.py
#

import turbogears
import cherrypy
from resource import Resource  # see the resource.py code below...

class Pages(Resource):
    db_modelname = 'pages'
    @turbogears.expose()
    def add(self, obj, **kw):
        if cherrypy.request.method != 'POST':
            raise cherrypy.HTTPError(500, "No you don't...")
        # do your pages-specific add work here...
        return dict(success=True)  # or whatever you want

class Root(controllers.Root):
    pages = Pages()

#
# resource.py
#

from sqlobject import SQLObjectNotFound
import turbogears
from turbogears import controllers
import model

class Resource(controllers.Root):
    db_modelname = ''  # override this in child resources

    @turbogears.expose()
    def default(self, *vpath, **params):
        if not vpath:
            return self.index(**params)
        # Make a copy of vpath in a list
        vpath = list(vpath)
        atom = vpath.pop(0)

        # See if the first virtual path member is a container action
        method = getattr(self, atom, None)
        if method and getattr(method, "expose_container"):
            return method(*vpath, **params)

        # Not a container action; the URI atom must be an existing ID
        # Coerce the ID to the correct db type
        ID = int(atom)
        try:
            obj = getattr(model, self.db_modelname).get(ID)
        except SQLObjectNotFound:
            raise cherrypy.NotFound

        # There may be further virtual path components.
        # Try to map them to methods in this class.
        if vpath:
            method = getattr(self, vpath[0], None)
            if method and getattr(method, "exposed"):
                return method(obj, *vpath[1:], **params)
            else:
raise cherrypy.NotFound("We can't %s with %s" % (`vpath[0]`, obj))

        # No further known vpath components. Call a default handler.
        return self.show(obj, *vpath, **params)

    @turbogears.expose()
    def show(self, obj):
raise NotImplemented("you must define your own 'show' method for your obj...")


Reply via email to