On Mon, Nov 23, 2009 at 11:34 AM, Ross Vandegrift <[email protected]> wrote:
> Hi everyone,
>
> I'm adding API functionality to an exiting app whose controller
> actions aren't close to being in shape for direct exposure.  This
> pretty much precludes me from turning them into REST controllers and
> accomplishing this task that way.
>
> So I've created a new api controller that will house the actions for
> programmatic access.  This has an unfortunate side effect of making my
> routing kind of difficult.
>
> For example, suppose I have model objects X and Y and the following API:
>
> class ApiController(BaseController):
>       �...@jsonify
>        def getXbyid(self, id):
>                q = meta.session.query(model.X)
>                result = q.get(id)
>                return {"result": result.__json__()}
>
>       �...@jsonify
>        def getXbyacct(self, acct):
>                q = meta.session.query(model.X)
>                result = q.filter_by(acct=acct).one()
>                return {"result": result.__json__()}
>
>       �...@jsonify
>        def getYbyname(self, name):
>                q = meta.session.query(model.Y)
>                result = q.filter_by(name=name).one()
>                return {"result": result.__json__()}
>
>
> How can I effectively map these actions without listing each action in
> my routes?  The best I have come up with is to include a route for
> each parameter name I use:
>
> map.connect("/api/{action}/{id:[0-9]+}", controller="api")
> map.connect("/api/{action}/{acct:[0-9]+}", controller="api")
> map.connect("/api/{action}/{name:[a-zA-Z0-9+}", controller="api")

The answer is to use a generic 'id' variable in the route, and to
rename the variable in the action.  This is the philosophy behind the
default "/{controller}/{action}/{id}" route.

map.connect("/api/{action}/{id}", controller="api")

#### Actions
def by_id(self, id):
    id = self._get_int_id(id)
    ...

def by_acct(self, id):
    acct = self._get_int_id(id)
    ...

def by_name(self, id):
    name = self._get_alphanumeric_id(id)
    ...

#### Private methods, maybe in base controller
def _get_int_id(self, id, errmsg="Invalid numeric ID."):
    try:
        return int(id)
    except ValueError:
        abort(404, errmsg)

NAME_RX = re.compile(R"^[a-zA-Z0-9]+$")

def _get_alphanumeric_id(self, id, errmsg="ID may contain only letters
and digits."):
    if not NAME_RX.match(id):
        abort(404, errmsg)
    return id

-- 
Mike Orr <[email protected]>

--

You received this message because you are subscribed to the Google Groups 
"pylons-discuss" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/pylons-discuss?hl=.


Reply via email to