Hi Brian,

I have been following this discussion with interest, but have been hesitant
to comment -- my first Pylons project is only about 70% done, and I don't
have any formal education in computer science. Keeping that in mind, and
inviting further commentary on potential issues with the approach below,
here's how I've been working through those issues on my own project.

If I have a procedure needed by multiple controllers or even multiple
actions on one controller, I write it as a helper function. For instance, if
you had a helper function called "getphotos(user)" that retrieved all of the
information for the photo section of their profile and formatted it in a
consistent way, you could reuse that function across controllers. You might
have one primary controller that renders the main page and would check for
photo information and then pass the returned data from getphotos(user) to
the appropriate template. If someone instead accessed a photo-specific page
that did use a separate controller, it could also access getphotos(user) to
retrieve the data.

Depending on exactly what the controller needs to retrieve, the helper
function can be defined to accept multiple arguments or optional arguments
so it returns what you need. That way, in the photo example, it could return
one photo for a page viewing a single photo (request from photo controller),
or multiple photos (request from a more general controller), saving you from
having to use more than one controller, and keeping all the related code in
one spot.

I apologize if I'm missing something very basic about your question, but I
really wanted to get involved in this discussion to learn more about large
Pylons projects and what kinds of issues my current methods might raise.
Sometimes I'm still in the novice-phase of problem solving by relentless
trial and error, so I find an approach that works for me in one particular
situation, without the experience to see where it might fail on a larger
deployment.

Best,
Eric







On Fri, Aug 6, 2010 at 8:53 PM, BrianTheLion <[email protected]> wrote:

> It seems like building a REST application is The Right Thing To Do. I
> tend to want to create a controller for each entity in my object
> model, and the rationale behind the REST paradigm gives this idea some
> support.
>
> I also appreciate the "Pylons is for HTTP and nothing more"
> convention. I am, however, left to wonder how I should go about
> building all the other stuff that we need from a web application, the
> machinery that lives between the database and the templates in
> particular. Assume for a moment that we are writing a Facebook work-
> alike in Pylons. Then, a GET of
> http://pylonsfacebook.com/user/brianthelion
> would be a request - and I'll use Facebook-speak here - to view
> BrianTheLion's "profile." If we're following the REST formula that
> we've argued for, then UserController.show(id=brianthelion) is getting
> executed. Awesome.
>
> At this point in the example, though, there is giant code-hole. On
> Facebook, a user's profile is an extremely complicated UI. It's a
> "hybrid view" (is there a better term?) of data from many different
> model entities: user, event, photo, message, mail, news, etc, etc. To
> build our work-alike, we need to take information about the user, the
> events he's invited to, the photo's he's in, the things his friends
> are saying, etc, and render all of that to fun-to-look-at HTML. So,
> the context of our PylonsFacebook, the question is: How does
> UserController.show() go about producing this immensely complicated
> output? How should all of the code between HTTP and HTML - and there's
> a lot of it; the majority, in fact - be encapsulated? How can we best
> make it reusable?
>
> SQLAlchemy aside, this territory seemed pretty lawless to me. In my
> naivety I came up with the idea of "named views." For example, a GET
> of http://pylonsfacebook.com/photo/981388324/icon and
> http://pylonsfacebook.com/photo/981388324/full would render the "icon"
> and "full res" views of that photo, respectively. Pretty self-
> explanatory. This made some nice sense because then for the
> PhotoController I'd have a "show_icon" method and a "show_fullres"
> method, as well as a "photo.mako" with "icon" and "fullres" defs. The
> rendered HTML output of the aforementioned URLs served as nice visual
> building blocks for more complicated web pages, and GET-ing them
> allowed me to test the code easily.
>
> I ran into problems, though, when I started needing to build "hybrid"
> views, named views that depended on other named views. For example,
> http://pylonsfacebook.com/user/brianthelion/photos would call
> UserController.show_photos(id=brianthelion). It's output would depend
> on the output of, say, PhotoController.show_icon(id=29459285) and
> PhotoController.show_icon(id=299498594). So then I'd need to
> instantiate a PhotoController from within my UserController, and that
> seemed - at least in MY mind - to break the Pylons paradigm.
>
> Any thoughts? Thanks a ton for everything that has already been
> offered up!
>
> Cheers,
> ~br
>
>
> On Jul 23, 8:17 am, Diana Clarke <[email protected]> wrote:
> > 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+enab...
> >
> > 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]<pylons-discuss%[email protected]>
> .
> For more options, visit this group at
> http://groups.google.com/group/pylons-discuss?hl=en.
>
>

-- 
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