[Zope-dev] __before_publishing_traverse__ calls RESPONSE.redirect(): is there another way to change the browser URL?

Casey Duncan casey@zope.com
Mon, 23 Sep 2002 23:45:51 -0400


----- Original Message -----
From: "Craeg K Strong" <cstrong@arielpartners.com>
To: <zope-dev@zope.org>
Sent: Monday, September 23, 2002 10:59 PM
Subject: [Zope-dev] __before_publishing_traverse__ calls
RESPONSE.redirect(): is there another way to change the browser URL?


> Hello:
>
> I have defined a __before_publishing__traverse__() method in my Zope
product.
>
> Its job is to redirect the URL displayed in the browser to a nice looking
> URL, something like
>
> "../myapp/invoices/123"
>
> instead of
>
> "../myapp/execute"

__before_publishing__traverse__() doesn't affect the way the url looks to
the browser. Although it can change the path being traversed inside Zope if
you wish. It effectively lets any traversed object affect the rest of the
traversal in some arbitrary way, or do some work before it is itself
traversed.

> That way all my ZPT forms can call the same method: execute(),
> and I don't hardcode any URLs in my ZPTs.  The objective is to
> encapsulate my resource-to-URL mapping so that it can be changed
> independently from the ZPT code.
>
> I don't want to use setVirtualRoot, because I want to change the entire
> URL, not just "all but the leaf"

I'm not following this.

> The problem is that __before_publishing_traverse__ is getting called
*twice*
> for each button press.
>
> *First* it gets called with the "../myapp/execute" URL.  This is when I
> call RESPONSE.redirect()
>
> *Second* it gets called with the "../myapp/invoices/123" URL
>
> I am trying to understand how Zope works with the HTTP REDIRECT machinery.

__before_publishing_traverse__ is called once for any object that defines it
each time that object is traversed during a web request. A redirect
generates a whole new web request, so this causes another whole set of
object traversals.

> Is there a way to make the URL that is actually displayed in the browser
> *different* from the Zope method name you are calling, aside from using
> RESPONSE.redirect()?

Redirect would not do this. Redirect changes the URL and makes the browser
go to that URL. Whether that URL is a complete traversal to a method depends
on your application. For example, a humble Python script has a traversal
hook of the aforementioned variety that eats the rest of the URL path
elements and binds them to the script's namespace, by default under the name
"traverse_subpath". For example, given a Python script "pyscript" in your
Zope root directory, then the following URL would call it:

http://zopeserver/pyscript/more/path/elements

When called, the script would have the traverse_subpath set to the value
['more','path','elements']. So the URL does not point to a method in this
case. This is the easiest way to gather data from URL path elements.

To do the same in external Python code, take a gander at the traversal hook
in {Zope}/lib/python/Shared/DC/Scripts/Bindings.py which is the code that
Python scripts use.

hth,

-Casey