url path remainder as a script parameter?
I'm trying to provide a Zope interface for an existing photo album application that has an XML-RPC interface. The application contains a very large number of pictures that can by queried in various ways (time, event, featured people, etc.). I do not want to create Zope folders, but I do want the URLs to suggest that the pictures are stored in a folder hierarchy. For instance: http://abc.com/photos - this is root of photo archive http://abc.com/photos/<person> - a person-specific photo album - presenting available years http://abc.com/photos/<person>/<year> - a person-specific, year-specific album - presenting available months http://abc.com/photos/<person>/<year>/<month> - a person-specific, month-specific album - presenting available days http://abc.com/photos/<person>/<year>/<month>/<day> - a person-specific, day-specific album - presenting available thumbs http://abc.com/photos/<person>/<year>/<month>/<day>/<pic number> - a pic... It seems clear that I need to add a something to the Zope root having the id "photos", but is it a Python Script or a Product? I tried creating a Product and setting the __getitem__ method, but it didn't work. While I know the Zope-way is to store the objects in the Zope database, surely what I am trying to do is not uncommon either - so how do people normally do this? Thanks! Kent
--On Samstag, 19. Februar 2005 20:53 Uhr -0800 Kent Watsen <kent@watsen.net> wrote:
It seems clear that I need to add a something to the Zope root having the id "photos", but is it a Python Script or a Product? I tried creating a Product and setting the __getitem__ method, but it didn't work.
Usually every Product has to provide a constructor manage_addSomething() that creates an instance of the Product in the context of the container where it is called...there are tons of example in every single Zope Products...just look through the existing sources. -aj
Kent Watsen wrote at 2005-2-19 20:53 -0800:
... It seems clear that I need to add a something to the Zope root having the id "photos", but is it a Python Script or a Product?
A Python script could do what you would (by decoding the "traversal_subpath"). -- Dieter
Thanks for the pointer! I can get it to work when adding the Script directly, but traverse_subpath does not work when I try to do the same with a Script "Method" [index_html] added to a ZClass in a Product I created inside the ZMI - when my URL contains a path beyond the product, Zope displays a "Cannot locate object" error... Any pointers on how to get traverse_subpath (or something like it) to work in a Product? Thanks! Kent Dieter Maurer wrote:
Kent Watsen wrote at 2005-2-19 20:53 -0800:
... It seems clear that I need to add a something to the Zope root having the id "photos", but is it a Python Script or a Product?
A Python script could do what you would (by decoding the "traversal_subpath").
Kent Watsen wrote at 2005-2-21 01:21 -0800:
... I can get it to work when adding the Script directly, but traverse_subpath does not work when I try to do the same with a Script "Method" [index_html] added to a ZClass in a Product I created inside the ZMI - when my URL contains a path beyond the product, Zope displays a "Cannot locate object" error...
"index_html" is only automatically added after the complete URL. There is a mixin class around (though I do not know its name!) that provides traversal control for ZClasses. You will need to search the Web to locate it -- or use a Python Script outside a Z Instance... -- Dieter
Dieter, thank you for your time and patience! I found a product called DirArg that seems to do the trick, but its own documentation says that it is deprecated by traverse_subpath... I also found http://zope.org/Members/lalo/scriptclass and have now written a simple Python-based product, which I am now modifying to derive off the Script class, but the instructions are a little cryptic... But I think that I'm still missing something fundamental - a normal product has a class that has an index_html method - is the goal for my Script-derived product class's index_html method to have the traverse_subpath variable defined? Also, the normal product's index_html is initialized using something like: index_html = DTMLFile("index_html", globals()) Is there such a thing as: index_html = PythonScriptFile("index_html", globals()) ??? I googled, but couldn't find anything... Again, my high-level goal is to have a Product that uses traverse_subpath to form a query against another application - surely this is not uncommon... Thanks! Kent Dieter Maurer wrote:
Kent Watsen wrote at 2005-2-21 01:21 -0800:
... I can get it to work when adding the Script directly, but traverse_subpath does not work when I try to do the same with a Script "Method" [index_html] added to a ZClass in a Product I created inside the ZMI - when my URL contains a path beyond the product, Zope displays a "Cannot locate object" error...
"index_html" is only automatically added after the complete URL.
There is a mixin class around (though I do not know its name!) that provides traversal control for ZClasses. You will need to search the Web to locate it -- or use a Python Script outside a Z Instance...
On Tue, 22 Feb 2005 01:34:59 -0800, Kent Watsen <kent@watsen.net> wrote:
Dieter, thank you for your time and patience!
I found a product called DirArg that seems to do the trick, but its own documentation says that it is deprecated by traverse_subpath...
I also found http://zope.org/Members/lalo/scriptclass and have now written a simple Python-based product, which I am now modifying to derive off the Script class, but the instructions are a little cryptic... But I think that I'm still missing something fundamental - a normal product has a class that has an index_html method - is the goal for my Script-derived product class's index_html method to have the traverse_subpath variable defined?
Also, the normal product's index_html is initialized using something like: index_html = DTMLFile("index_html", globals()) Is there such a thing as: index_html = PythonScriptFile("index_html", globals()) ??? I googled, but couldn't find anything...
Again, my high-level goal is to have a Product that uses traverse_subpath to form a query against another application - surely this is not uncommon...
Actually, it appears to be. I had the same problem with my as-yet incomplete blog that I wanted to have URLS much as you describe. I figured it out though. traverse_subpath is only set for ZPT, DTML and Script (Python) objects, as far as I can see, so I snarfed the code from the python script class. You need this code for it: This will allow Zope to traverse down as far as it likes and add it to a variable in request called 'traverse_subpath' def __before_publishing_traverse__(self, self2, request): path = request['TraversalRequestNameStack'] if path and hasattr(self.aq_base, path[-1]): return subpath = path[:] path[:] = [] subpath.reverse() request.set('traverse_subpath', subpath) and then in your index_html method you need to decode the subpath and then do what you want with it, here's what I do at the moment: def index_html(self, REQUEST=None, *args, **kw): """Serve up blog requests""" traverse_subpath = REQUEST['traverse_subpath'] if len(traverse_subpath) == 0: # We return the index page return self.blog_index_html(self, REQUEST, **kw) elif len(traverse_subpath) == 1: item = traverse_subpath[0] if re.match(r"[1-2][0-9]{3}", item) is not None: return "Year match %s" % item else: return "Other match %s" % item else: return "Deep nesting, item is %s" % '/'.join(traverse_subpath) Hope this helps a bit. The individual path elements are stored as an array, starting from the left most element after the last 'real' object, ie the instance of this class. -- Phillip Hutchings http://www.sitharus.com/ sitharus@gmail.com / sitharus@sitharus.com
Phillip, Thank you for your email - very helpful! Before getting your email, I also started snarfing the PythonScript.py code into something I could whittle down to the minimal code needed. However, it looks like you have beat me to it, but your solution leaves with with a few questions: 1) Are you saying that it is unnecessary for my Product's class to inherit from the Script class? Are there any special classes that it should it inherit from? 2) I found __before_publishing_traverse__ in the Bindings .py, do I just put this method in my poduct's class? PS: I might note that zope-2.7.2's method looks a little different... 3) I understand having an index_html method, but how did __before_publishing_traverse__ method get executed before its called? Thanks! Kent Phillip Hutchings wrote:
Actually, it appears to be. I had the same problem with my as-yet incomplete blog that I wanted to have URLS much as you describe. I figured it out though. traverse_subpath is only set for ZPT, DTML and Script (Python) objects, as far as I can see, so I snarfed the code from the python script class. You need this code for it:
This will allow Zope to traverse down as far as it likes and add it to a variable in request called 'traverse_subpath'
def __before_publishing_traverse__(self, self2, request): path = request['TraversalRequestNameStack'] if path and hasattr(self.aq_base, path[-1]): return subpath = path[:] path[:] = [] subpath.reverse() request.set('traverse_subpath', subpath)
and then in your index_html method you need to decode the subpath and then do what you want with it, here's what I do at the moment: def index_html(self, REQUEST=None, *args, **kw): """Serve up blog requests""" traverse_subpath = REQUEST['traverse_subpath'] if len(traverse_subpath) == 0: # We return the index page return self.blog_index_html(self, REQUEST, **kw) elif len(traverse_subpath) == 1: item = traverse_subpath[0] if re.match(r"[1-2][0-9]{3}", item) is not None: return "Year match %s" % item else: return "Other match %s" % item else: return "Deep nesting, item is %s" % '/'.join(traverse_subpath)
Hope this helps a bit. The individual path elements are stored as an array, starting from the left most element after the last 'real' object, ie the instance of this class.
On Thu, 24 Feb 2005 21:46:50 -0800, Kent Watsen <kent@watsen.net> wrote:
Phillip,
Thank you for your email - very helpful!
Before getting your email, I also started snarfing the PythonScript.py code into something I could whittle down to the minimal code needed. However, it looks like you have beat me to it, but your solution leaves with with a few questions:
1) Are you saying that it is unnecessary for my Product's class to inherit from the Script class? Are there any special classes that it should it inherit from?
No special classes, except for the normal classes to make a product.
2) I found __before_publishing_traverse__ in the Bindings .py, do I just put this method in my poduct's class? PS: I might note that zope-2.7.2's method looks a little different...
I adapted the function slightly, so it might be a bit different.
3) I understand having an index_html method, but how did __before_publishing_traverse__ method get executed before its called?
By zPublisher iirc. It just happens automagically ;) -- Phillip Hutchings http://www.sitharus.com/ sitharus@gmail.com / sitharus@sitharus.com
Phillip Hutchings wrote:
3) I understand having an index_html method, but how did __before_publishing_traverse__ method get executed before its called?
By zPublisher iirc. It just happens automagically ;)
I hate that word, I vote for a swear jar for anyone who uses it on the list. Anyway, the name of the hook kind of gives the game away. __before_publishing_travese__ is called before the publisher traverse through the object. There's also __bobo_traverse__, which is similar, but I forget how it works its way into the picture... Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
I hate that word, I vote for a swear jar for anyone who uses it on the list.
Here, have 50c ;)
Anyway, the name of the hook kind of gives the game away. __before_publishing_travese__ is called before the publisher traverse through the object.
There's also __bobo_traverse__, which is similar, but I forget how it works its way into the picture...
iirc, __before_publishing_traverse__ gets called after the inital traversal has found the object, but before the publishing traverse (as it says ;), so it's a fairly easy way to inject an object that wouldn't be found. __bobo_traverse__ gets called during the traverse, so it can be a but harder to deal with. Of course, I could be completely wrong, but that's as I understand it. -- Phillip Hutchings http://www.sitharus.com/ sitharus@gmail.com / sitharus@sitharus.com
On Sat, Feb 26, 2005 at 11:49:18AM +1300, Phillip Hutchings wrote:
iirc, __before_publishing_traverse__ gets called after the inital traversal has found the object, but before the publishing traverse (as it says ;),
You know, I've never really understood that... Once you've found the object, isn't traversal done? What's the difference between "initial traverse" and "publishing traverse"? -- Paul Winkler http://www.slinkp.com
On Fri, 25 Feb 2005 18:06:22 -0500, Paul Winkler <pw_lists@slinkp.com> wrote:
On Sat, Feb 26, 2005 at 11:49:18AM +1300, Phillip Hutchings wrote:
iirc, __before_publishing_traverse__ gets called after the inital traversal has found the object, but before the publishing traverse (as it says ;),
You know, I've never really understood that... Once you've found the object, isn't traversal done? What's the difference between "initial traverse" and "publishing traverse"?
Not entirely sure. I think one locates and finds the objects from the storage, and the other finds the actual object that is published, which isn't always the one in the file system. I also recall that initially security is ignored as the objects need to be loaded to check security, then the publish traverse takes security in to account. -- Phillip Hutchings http://www.sitharus.com/ sitharus@gmail.com / sitharus@sitharus.com
Paul Winkler wrote at 2005-2-25 18:06 -0500:
On Sat, Feb 26, 2005 at 11:49:18AM +1300, Phillip Hutchings wrote:
iirc, __before_publishing_traverse__ gets called after the inital traversal has found the object, but before the publishing traverse (as it says ;),
You know, I've never really understood that...
"__before_publishing_traverse__" is looking for nothing and cannot return an object. But it can modify the request and thereby change what is looked for in the future. "__bobo_traverse__" is looking for "name" and it must return an object. It, too, can modify the request and change what is looked for in the future. However, this is a bit dangerous, as "__bobo_traverse__" (unlike __before_publishing_traverse__") is also used by "Traversable.[un]restrictedTraverse" and "Products.PageTemplateFile.Expressions.restrictedTraverse". -- Dieter
participants (6)
-
Andreas Jung -
Chris Withers -
Dieter Maurer -
Kent Watsen -
Paul Winkler -
Phillip Hutchings