I've written two pylons apps now: the first a typical web application,
and the second a RESTful API.

In both cases I started with:

    paster create -t pylons helloworld

followed by (for the web application):

    paster controller hello

or (for the RESTful API):

    paster restcontroller hello hellos

These code generation tools allowed me to get up and running fast, and
made it easier to find applicable examples on the net since I was
essentially following a set convention. I also had enough domain
specific work to do as it was, and trusted that there were smart peeps
behind pylons and paster, and that they had already iterated on this
part of the stack for me.

The generated code from 'restcontroller' was especially helpful -- it
made building a RESTful API a simple paint-by-numbers exercise.

    HTTP_DELETE maps to delete(): you just need to implement some
delete resource code
    HTTP_POST maps to create(): you just need to implement some create
resource code
    HTTP_PUT maps to update(): you just need to implement some update
resource code
    ....

    
http://wiki.pylonshq.com/display/pylonscookbook/How+map.resource+enables+controllers+as+services

Until I had a better idea about what I wanted from the controllers, I
just did what the generated code comments told me to do, but at the
same time was careful to move similar code to the BaseController
(base.py) and use consistent form parameter naming conventions across
resources.

Eventually I had N controllers that each implemented index(), show(),
create(), update(), and delete(). Each of these methods was only 3
lines of code:

    line 1: gather up the form parameters, or payload
    line 2: pass them to the service layer for processing
    line 3: serialize the response (json or XML)

I've since been able to move pretty much all of this code to the
BaseController (still just ~100 lines of code), and each of the N rest
controllers just extend BaseController and define the service they
should defer to for processing.

So, in my case, I was able to get away with dead simple controllers: a
couple of lines max with only an __init__() method.

My controllers are now, by definition, consistent -- making it easy to
write libraries on the flip-side to consume them.

 -- show() for every resource accepts "include" options allowing you
to ask for nested child resources in one HTTP request rather than
making two requests (one for each resource). For example: get a folder
and the folder's child files in one request.

-- index() for every resource accepts search filters, sorting options,
include options, paging options etc and always returns a collection
with the resulting pagination info (page, pages, per_page, total).

 etc...

So, I guess my answer to what belongs in a pylons controller is almost
*nothing*. My general rule of thumb is that I use pylons for all
things HTTP and nothing more:

    - HTTP URIs (id, format)
    - HTTP methods (PUT, POST, GET...)
    - HTTP routing (map.resource)
    - HTTP form parameters (request.params.get)
    - HTTP payload (request.body)
    - HTTP response codes (401 Unauthorized...)

The payload gets turned into an incoming DTO (data transfer object),
the service knows what to do with it and returns an outgoing DTO, the
DTO knows how to serialize itself based on the format.

    def show(self, id, format='json'):

The services I keep mentioning are in another python application
completely -- this is to encourage the "pylons is for HTTP and nothing
more" convention.

The services are actually pretty complex in cases: persisting data to
a cloud and databases (SQLAlchemy), firing events to RabbitMQ,
triggering sub-actions, enforcing ACLs, validation, business logic,
etc. In my opinion, none of this belongs in a controller.

BTW, I mean no offense with: "pylons is for HTTP and nothing more".
It's just a convention we employ for this particular project to keep
the responsibilities clear. And it is definitely more applicable for a
RESTful API vs. a web application with views using Mako templates for
example. In that case, my controllers do have a bunch of tmpl_context
assignments.

Cheers,

--diana

-- 
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=en.

Reply via email to