[Zope] a simple design problem, a Zope bug and a fix

Ivan Kurmanov iku@tut.by
Fri, 5 Oct 2001 05:23:18 +0300


--5vNYLRcllDrimb99
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,

Here I have several things to report.  The message might get long, but
that is what I have to say.  I hope very much that someone of Zope
developers/maintainers is keeping an eye on this mail-list and will
forward my message to a responsible person.

First, the Problem.  A section of my zope-based site might have
folders and even without folders it is not a single-layer structure.
To explain: if I have an object "O" in folder "F", we access it as
"http://site/F/O" (0).  If we have a sub-folder 'SF' in 'F', we access
object "O2" in it by "http://site/F/SF/O2" (1).  But even without
"SF", if we call a method 'M' on object 'O', we already have a
three-level URL: "http://site/F/O/M" (2).

I create a simple navigational bar for my project that lives in /F.
For that I create the standard_html_header in /F.  Here is the
problem: how do I create a consistent link to the Home of the section
- to the "/F" folder?  And to several methods of it?

Of course I could simply hardcode it into a usual HTML link, e.g. <a
href="/F/method1">. But that solution is not for a responsible person.
I want site to be exportable and to stay consistent even if I move it
around.  Imagine that I rename /F to something else and will have the main
navigational links get broken.

I could have put simply a relative link <a href="./"> for the /F
folder.  But that link will not anymore be valid in cases (1) and (2),
because their context is deeper and it would (could) instead send user
to "http://site/F/SF" and "http://site/F/O" respectively.

Similarly it may seem that relative links to reference a method in /F
folder are fine, e.g. <a href="method1">.  But what if want those
links to yield the same result ("http://site/F/method1") independently
of what particular page user has clicked them on!  While in cases (1)
and (2) user will get two other different results.

I understand that probably there is a solution to the problem, which
is well-known to experienced Zopers, but for me it was a challenge to
solve.

The Solution:

 (a) Regarding home-folder methods.  Your methods are objects and you
can use "url" attribute on them.  In DTML entity notation it may look
like this:

  <a href="&dtml.url-method1;">...</a>

This will find an existing 'method1' in '/F' folder and will always
generate a correct link to it, unless you also have a 'method1' object
in one of your subfolders.

This solution will also NOT work if you need to reference a method
which doesn't exists as a DTML method object or python script object,
but which is defined internally by Zope classes or by a Zope
Product. (in particular, all 'manage_...' methods)

 (b) In the home folder ("/F") you create a special object, which will
serve you as a point of reference, and which will return you the URL
of the folder it lives in.  You than take this URL and you can append
any document or method names to it. 

What kind of object can do this? 

I tried several kinds of...

The simplest solution that I found is a single-line Python script: 

   return container.absolute_url() 

Script must lie in the home folder.  Then you reference it like this
in your standard_html_header: "<a href="&dtml-home_folder_url;/method1">,
assuming that the script's id is 'home_folder_url'.

In principle, it seems that things like this: 
  <dtml-var expr="container.absolute_url()"> 

in /F/standard_html_header must work, but it doesn't work stably on my
installation.  And it may be a bit too inelegant for use it in the <a
href="..."> tag.


Secondly, the Bug. 

And now we came to a bug description: I claim that absolute_url()
method of the Traversable class has a bug, at least in Zope 2.4.1

The bug causes incorrect URL returned sometimes when a it is executed
on an aquired object.  For instance, if in object /F/O I evaluate
self.container.absolute_url() what I get will depend on the request
context:

  if the requested url was: "http://site/F/something", then the URL
  returned in object O will be fine: "http://site/F"

  if the requested url was: "http://site/F/SF/something", then the URL
  returned *might* be "http://site/F/SF/something/F". 

*Might* here means that if the absolute_url() is executed in a Product
class definition, it will go wrong, but if it is executed from a
python script (like the one above), it will work fine.  I suppose that
has something to do to with the context (namespace) transfer to python
scripts.


Finally, a fix: I'm far from well-understanding the change I made to
the Zope code, but it works better for me now.  I attach to this
message a patch for Traversable.py file.


Any comments welcome.

Cheers!

-- 
Ivan Kurmanov


--5vNYLRcllDrimb99
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=Traverable-patch

--- /home/ivan/master-copy/Zope-2.4.1-src/lib/python/OFS/Traversable.py	Thu Aug 30 16:07:49 2001
+++ /home/ivan/zope/lib/python/OFS/Traversable.py	Fri Oct  5 04:59:50 2001
@@ -130,7 +130,7 @@
         '''
         path = (self.getId(),)
         
-        p = aq_parent(aq_inner(self))
+        p = aq_parent( aq_base(aq_inner(self)) ) 
         if p is not None: 
             path = p.getPhysicalPath() + path
 

--5vNYLRcllDrimb99--