Re: [Zope] help with __bobo_traverse__
Mohamed Lrhazi <mohamed@your-site.com> writes:
--On Thursday, May 27, 2004 9:15 PM +0100 Matt Hamilton <matth@netsight.co.uk> wrote:
My initial thought is that maybe there is no context wrapper for viewDomain when you return it. I can't remember if it is added automaticcally or not. You could try:
return getattr(self, 'viewDomain').__of__(self)
and see if that works.
I will try that....
Having said that, taking another look at your code, I think it works as expected. The first call to __bobo_traverse__ gets 'foobar', but how does foobar get '1'? Does an object called '1' exist anywhere?
I said I was a newbie, didn't I? :)
In <http://10.0.10.28:8080/yspanel/foobar/1/2/3/4>
There is no object "foobar" nor "1" nor "2" ....
yspanel is an instance of My product though. and I am trying to figure out how to use __bobo_traverse__ to call a method to handle the above request, where everything, from foobar and on, is parameters or commands...
I do this in two toy products, BlogFace and BlogTopic. http://zope.org/Members/karl/index_html/BlogFace/BlogFace http://zope.org/Members/karl/index_html/BlogTopic/BlogTopic BlogFace uses __bobo_traverse__. If name actually exists, return it for publishing. If name is an int, add something to the REQUEST and return self. If name is in a parameter dict, add something to REQUEST and return self. If no actual subobjects get in the way, we end up at self's index_html, which does something with these stored agruments. def __bobo_traverse__(self, REQUEST, name): """ Consume trailing URL path and turn into arguments so long as they are convertable to ints. Otherwise, traverse normally with collected arguments. Note that this shadows subobjects with IDs that are convertable to ints. """ if re.match('^[0-9]+$', name): if not REQUEST.has_key('traverse_date'): REQUEST['traverse_date'] = [] (REQUEST['traverse_date']).append(name) elif name in self.traverseParamOpts.keys(): if not REQUEST.has_key('traverse_params'): REQUEST['traverse_params'] = [] (REQUEST['traverse_params']).append(name) else: # normal traverse. This can raise an AttributeError. What can # we raise to get the publisher to do what it does in other # cases, besides making and raising a notFoundError ourselves? return getattr(self, name) return self BlogTopic does this more efficiently by munging the traversal stack in __before_publishing_traverse__, so that all of those traversal calls are short-circuited. # should be using the tools in BeforeTraverse.py? def __before_publishing_traverse__(self, obj, req): """ If the traversal stack is all intable strings that don't lead to attrs or items, put the date represented in the request and lop the stack, causing the publisher to call us for the next publishing step. """ stack = req['TraversalRequestNameStack'] # do nothing unless we have only intable strs to traverse overall # XXX use something faster than re.match(str)? if stack and (len(filter(lambda x: re.match('^[0-9]+$', x), stack)) != len(stack)): return # Do nothing if there's an attr or item to publish, allows # things like custom views for dates. # This isn't rigorous, there could still be something to publish, # but there isn't a mechanism to find any name that # BaseRequest.traverse would publish, other than copying the code. stack.reverse() if stack: self_base = aq_base(self) if hasattr(self_base, stack[0]): return try: dummy = self_base[stack[0]] return except: pass # stop looking for next obj to publish by emptying stack req['TraversalRequestNameStack'] = [] try: req['BlogTopicDate'] = seqToDate(stack) except: req['TraversalRequestNameStack'] = [self.dateErrorSkin] Munging the traversal stack can have weird consequences for things like breadcrumbs. -- Karl Anderson kra@monkey.org http://monkey.org/~kra/
--On Thursday, May 27, 2004 3:45 PM -0700 Karl Anderson <kra@monkey.org> wrote:
yspanel is an instance of My product though. and I am trying to figure out how to use __bobo_traverse__ to call a method to handle the above request, where everything, from foobar and on, is parameters or commands...
I do this in two toy products, BlogFace and BlogTopic.
http://zope.org/Members/karl/index_html/BlogFace/BlogFace http://zope.org/Members/karl/index_html/BlogTopic/BlogTopic ...
Thank you so much Karl, that was a comprehensive answer. I got it working using the second method you showed: In case this is of use to any one: My application instance name, or id, is yspanel, now a URL like this: <http://10.0.10.28:8080/yspanel/dview/arg1/arg2/arg3/any/thing/at/all> would result in: <http://10.0.10.28:8080/yspanel> which would call my normal index_html method with the following list added to the REQUEST dict: REQUEST['YSURLARGS'] = ['dview', 'arg1', 'arg2', 'arg3','any','thing','at','all'] all thanks to this method added to my class: def __before_publishing_traverse__(self, obj, req): """ """ stack = req['TraversalRequestNameStack'] stack.reverse() if len(stack) and stack[0] == 'dview': # stop looking for next obj to publish by emptying stack req['TraversalRequestNameStack'] = [] req['YSURLARGS'] = stack[:]
Hi! Mohamed Lrhazi wrote:
def __before_publishing_traverse__(self, obj, req): """ """ stack = req['TraversalRequestNameStack'] stack.reverse()
I doubt you want to do that. 'stack' is not a copy. So if your condition is not true, TraversalRequestNameStack is screwed up.
if len(stack) and stack[0] == 'dview': # stop looking for next obj to publish by emptying stack req['TraversalRequestNameStack'] = [] req['YSURLARGS'] = stack[:]
Something like that should be better: def __before_publishing_traverse__(self, obj, req): """ """ stack = req['TraversalRequestNameStack'] if stack and stack[-1] == 'dview': # stop looking for next obj to publish by emptying stack stack.reverse() req['TraversalRequestNameStack'] = [] req['YSURLARGS'] = stack[:] BTW: Why can't you simply use traverse_subpath? Cheers, Yuppie
--On Friday, May 28, 2004 10:30 AM +0200 yuppie <y.2004_@wcm-solutions.de> wrote:
Hi!
Mohamed Lrhazi wrote:
def __before_publishing_traverse__(self, obj, req): """ """ stack = req['TraversalRequestNameStack'] stack.reverse()
I doubt you want to do that.
I wont do that. Thanks a lot.
'stack' is not a copy. So if your condition is not true, TraversalRequestNameStack is screwed up.
if len(stack) and stack[0] == 'dview': # stop looking for next obj to publish by emptying stack req['TraversalRequestNameStack'] = [] req['YSURLARGS'] = stack[:]
Something like that should be better:
def __before_publishing_traverse__(self, obj, req): """ """ stack = req['TraversalRequestNameStack'] if stack and stack[-1] == 'dview': # stop looking for next obj to publish by emptying stack stack.reverse() req['TraversalRequestNameStack'] = [] req['YSURLARGS'] = stack[:]
BTW: Why can't you simply use traverse_subpath?
Never heard of it :) Mohamed~
Mohamed Lrhazi wrote:
BTW: Why can't you simply use traverse_subpath?
Never heard of it :)
It's what you SHOULD be using rather than fussing with traversal hooks, especially if you'rea newbie. Both ZPT's and Script(Python)'s have a traverse_subpath variable in their namespace, so for example: http://www.example.com/my_ps_or_zpt/1/2/3 ...will give you: print traverse_subpath ['1','2','3'] cheers, Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
participants (4)
-
Chris Withers -
Karl Anderson -
Mohamed Lrhazi -
yuppie