[Product-Developers] Re: Traversing from a z3c.form action handler

Martin Aspeli optilude+lists at gmail.com
Mon Feb 15 06:09:23 UTC 2010

cewing wrote:

> It was 3 am when I got to this point, but yes, that was the first thing I
> tried.  Response.redirect appears to lose the data I've set on the request
> in my form action.

Unless you pass it along (e.g. in a query string), that'll happen. A 
redirect just sends a 301 response to the browser telling it to load a 
new page.

You could construct a URL with a query string, though. That's probably 
the first thing I'd try.

> I remember reading a blog post at one point about using
> a traversal technique instead of response.redirect to keep the original
> request and all its data intact as you move from one page to another.  It
> seems that ControllerPageTemplates must use something like this, since all
> of their metadata contain references to 'TraverseTo'.

Yes, FormController works like this. All it's really doing is to look up 
another object, calling it to get a string of raw HTML, and returning 
that as the response body. So the browser (and hence the URL bar) has no 
idea what's going on. This is kind of like invoking an alternative page 

It's a bit confusing, though. It may work because you set something in 
the request and the same request object is used when you "traverse" to 
the other view/template/object. There's the potential for things to leak 
across the two views, though.

> I'm not terrifically concerned about the URL being wrong, but I've not
> managed to have returning the URL do anything.
> Here's what I have in the action so far:
> class AnimalTable(HydraCrudEditForm):
>      label = _(u'My Animals')
>      @button.buttonAndHandler(u'Change State', name='state_change')
>      def handle_state_change(self, action):
>          """ traverse to the content_status_share form for processing
>          """
>          true_context = self.context.context
>          selected = self.selected_items()
>          paths = []
>          if selected:
>              paths = [item.absolute_url_path() for id, item in selected]
>              self.request.form['paths'] = paths
>              path = true_context.absolute_url_path() +
> '/content_status_history'
>              state_view = true_context.restrictedTraverse(path)
>              return state_view()
>          else:
>              IStatusMessage(self.request).add("No animals selected",
> type=u'warning')
> Unfortunately, that just ends up by reloading the original form without any
> indication that anything has happened.

I think you'd need to override render() to conditionally return the 
state_view() stuff, and conditionally use the standard template (or call 
the base class version). render() is called after the action handler.


Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book

More information about the Product-Developers mailing list