Posts Tagged ‘routes’

CherryPy, RESTFul Routing

October 12th, 2008 by ScottK | 2 Comments | Filed in CherryPy

Using CherryPy as a web server allows us to quickly create services and gain a lot more free time, or rest. I don’t miss those times where we worked none stop on other frameworks to provide services to other apps.  OK moving from on project immediately to another project takes up that free time and the rest in between is not what I mean by RESTFul routing.

The buzzword RESTFul routing is really just a concept that states actions that you perform for updating your data can be attributed to the state the browser asks you to do it. Along with parameters that it sends. I won’t go into any full explanation of what Representational State Transfer is, but you can find a good explanation here RESTFul.

I do find that that having RESTFul controllers are a big benefit to integrating with Ruby on Rails apps, yet I’m not so hooked on the idea that RESTFul is the end all be all of web programming. There are time in even rails apps that you need to break that convention and create special routing configurations. CherryPy, through the routes, fully supports those as well.

I’ve created the downloadable CherryPy Example 3 so you can follow along.

Let’s start by looking at the natural RESTFul controller: controllers/users_controller.py. You’ll find that it holds the full RESTFul actions you would expect to find. Create, Index, Show, New, Update, Edit, Delete. All of these are completely usable due to the @cherrypy.expose decorator. Look at the controllers/hello_worlds_controller.py as well. You’ll find that none of the RESTFul actions are there at all.

In order to use both of these controllers you need to step outside of the “default” CherryPy tutorial and dig a little deeper. Hence is the reason why you’ll find in the libs folder the route_mapper.py. It’s the core of setting up the RESTFul routing. So let’s walk through the example step by step because it all starts with the deploy.py and follows step by step.

In my last post about CherryPy, The Deploy Script I only setup the first stage of running a CherryPy app. Only hinting on how to set up RESTFul routing. I made mention that two methods were left out. Now those are important.

The first of the two is the “load_default_routes” method. This method does not accept any arguments and setups up all your RESTFul routes by default. The second of the the two is the “load_custom_routes” which is what you’ll use to set up all your custom routing, or named routing.

You’ll notice in the example that I import these controllers during these methods. This is intentional because we absolutely have to have the con figs loaded, example 2. Along with each of the methods we are building a list of dict pertaining to specific information. Name, path, controller for both default and named routes, as well as specific action for the named routes.

In the deploy script the “server_start” method calls these two methods. Which then passes these as arguments to the lib.route_mapper library. This is where the routes magic happens. In lib you’ll find the route_mapper.py file give that a look.

By default CherryPy uses it’s own dispatcher to set up routing. This is not necessarily RESTFul. In that using the default you would have to call /users/index to access the UsersController index action. What we wanted was the RESTFul GET method /users. What about different format types as well? The routes_mapper library throws away the CherryPy dispatcher and uses the routes dispatcher instead.

That what this is doing:

d = cherrypy.dispatch.RoutesDispatcher()

Now that we have the routes library dispatcher for CherryPy we can set up routing as we need using the connect method.

Certainly in setting this up I discovered some really strange things which I’ve fixed in your example. But what it boils down to if you want to set up your own RESTFul routing or named routing is this: Order of Operation.

1. (controller)/:id.:format
2.(controller):id

If I called event/1.html it would find number one first. If I called event/1 it would find number two.

1. (controller):id
2. (controller):id.:format

In either case of calling event/1 or event/1.html it would always find number one.

This is true of all methods as well. The order of Create, Index, New, Show, Edit, Update seems to be the best mix for setting up the Routes mapper. In different orders the correct actions may not be called correctly.

You’ve now seem me use :id, and :format. What do these mean? They are merely the arguments I am passing to the controller action. You can certainly use what ever you need to.

Given that if in my load_default_routes I have:

routes = [
{"name"  : "post_comments",
"path"  : "post/:post_id/comments/:id",
"controller" : CommentsController()
}
]

I would need to have a comments_controller class with a show action. This action would have the arguments of:

def show(self, post_id, id):
...

So anything you prepend with “:” thus becomes an argument to your action method.

Really by taking the routes dispatcher from the default CherryPy dispatcher you can implement RESTFul routing. It really isn’t difficult to do as long as you do it in order of actions and as long as you understand what Representational State Transfer is all about. Even named and custom routes can be used if you wish.

Tags: , , ,

CherryPy Using Routes Library

June 23rd, 2008 by ScottK | No Comments | Filed in Python

I’m still plucking away at this project as time allows using CherryPy. This weekend I just started to use it and finally got a working environmental configuration system and then next step was to figure out if RESTful controllers could be used. As it turns out you can not only use RESTful controllers but have the additional benefit of format types as well (html, xml, json, etc).

This is due to the CherryPy RoutesDispatcher using the routes library. I’ve successfully setup dispatcher with RESTful routes and have tests to show that they work as planned.

I’ll do a follow up post with working examples this weekend.

Tags: , , ,