Re: [Zope3-Users] Specialized URL traversal.. Best way?
On Tue, Jan 03, 2006 at 05:37:30PM -0500, Wade Leftwich wrote: > Marius Gedminas wrote: > > On Thu, Dec 29, 2005 at 11:22:28PM -0700, Jeff Shell wrote: > >>Again, this is to have URLs like: > >> > >>myapp/@@tags/zope/viewlet > > How about this? It gives > zope.app.publication.publicationtraverse.PublicationTraverse.traverseName() > some extra work, but it doesn't mess with the request and leaves > request.URL reflecting the entire "path". > > ### > class BrowserViewStopTraversal(BrowserView): > implements(IPublishTraverse) > > def __init__(self, context, request): > self.context = context > self.request = request > self.traverse_subpath = [] > > def publishTraverse(self, request, name): > self.traverse_subpath.append(name) > return self > > def __call__(self): > """Just for example""" > return ("traverse_subpath = %s\nrequest.URL = %s" % > (self.traverse_subpath, self.request.URL)) I like it. Marius Gedminas -- The advertisement is the most truthful part of a newspaper. -- Thomas Jefferson signature.asc Description: Digital signature ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Specialized URL traversal.. Best way?
Marius Gedminas wrote: > On Thu, Dec 29, 2005 at 11:22:28PM -0700, Jeff Shell wrote: > >>Again, this is to have URLs like: >> >>myapp/@@tags/zope/viewlet >> >>And turn that into a catalog search for anyof {'zope', 'viewlet'} >> >>def publishTraverse(self, request, name): >>namestack = request.getTraversalStack() >>if name not in namestack: >>namestack.append(name) >>namestack.reverse() >>tags = tuple(namestack) >>request.setTraversalStack([]) >> >>results = TaggedArticleFinder(self.__name__,self.__parent__,tags) >>results.prepareSearch(request) >>return results >> >>The 'TaggedArticleFinder' then provides an interface that a view can >>be found for that displays the results. So I've got it all working >>now... > > > My coworker Albertas recently implemented something like this in > SchoolTool (I've CCed him). Unfortunately it turned out to have some > unforeseen consequences, for example, request.URL does not contain the > path elements you "eat" manually, breaking self-posting forms (those > that use ) and our login > mechanism. > > How about this? It gives zope.app.publication.publicationtraverse.PublicationTraverse.traverseName() some extra work, but it doesn't mess with the request and leaves request.URL reflecting the entire "path". ### from zope.interface import implements from zope.publisher.interfaces import IPublishTraverse from zope.app.publisher.browser import BrowserView class BrowserViewStopTraversal(BrowserView): implements(IPublishTraverse) def __init__(self, context, request): self.context = context self.request = request self.traverse_subpath = [] def publishTraverse(self, request, name): self.traverse_subpath.append(name) return self def __call__(self): """Just for example""" return ("traverse_subpath = %s\nrequest.URL = %s" % (self.traverse_subpath, self.request.URL)) ### http://namespaces.zope.org/zope"; xmlns:browser="http://namespaces.zope.org/browser"; i18n_domain="travtest" > ### http://localhost:8080/@@stoptrav/foo/bar/baz => traverse_subpath = [u'foo', u'bar', u'baz'] request.URL = http://localhost:8080/@@stoptrav/foo/bar/baz -- Wade Leftwich Ithaca, NY ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Specialized URL traversal.. Best way?
On 12/31/05, Marius Gedminas <[EMAIL PROTECTED]> wrote: > On Thu, Dec 29, 2005 at 11:22:28PM -0700, Jeff Shell wrote: > > Again, this is to have URLs like: > > > > myapp/@@tags/zope/viewlet > > > > And turn that into a catalog search for anyof {'zope', 'viewlet'} > > > > def publishTraverse(self, request, name): > > namestack = request.getTraversalStack() > > if name not in namestack: > > namestack.append(name) > > namestack.reverse() > > tags = tuple(namestack) > > request.setTraversalStack([]) > > > > results = TaggedArticleFinder(self.__name__,self.__parent__,tags) > > results.prepareSearch(request) > > return results > > My coworker Albertas recently implemented something like this in > SchoolTool (I've CCed him). Unfortunately it turned out to have some > unforeseen consequences, for example, request.URL does not contain the > path elements you "eat" manually, breaking self-posting forms (those > that use ) and our login > mechanism. Yeah, I know of that problem. Looking back, it looks like there have been a couple of ways of doing this. In Zope 2, there are a couple of prominent "cool path tricks" in the core content objects. Python Scripts allow you to get at the rest of the path. But the resulting affect is like you describe: the traversal stack is chopped off, and all URLs are relative to the script. We did a pretty cool ECommerce store in all Python Scripts and SQL Methods that did this to have URLs to products and categories, building up queries along the way. We quickly discovered that relative URLs didn't work in that scenario, so "./product/${product_id}" wouldn't work. I can see why it does this though - you didn't actually traverse to an object at that point in the path, so the request.parents attribute can't really have [, , , , , ] in it, when just takes the rest of the path and turns it into various script/object calls and queries. Zope 2 SQL Methods, on the other hand, allowed you do to direct traversal and turn a URL into a query. This may have even existed in the pre-principia version of Aqueduct. So for a two-category classified system you can do URLs like: /categorylist/category1_id/34/category2_id/12/list_ads.dtml What it does is actually create non-persistent traversable objects that implement the __bobo_traverse__ method. It accumulates the parts of the URL and somewhere along the way does the search. Acquisition binding and all of that still worked since the result was ultimately an object that was bound to the right parent. The code (In Zope 2: Shared/DC/ZRDB/DA.py, class Traverse) is rather old and cryptic, but it does provide an example of the other way of doing custom maps - traverse each name individually and create new objects along the way. This way, request.URL is not affected. If you were trying to make a custom traverser like date based archive searching and where at 2005/12/ in the url, you could then just have to go to the date. Both situations have their uses. They also have their consequences and side effects. Playing with the traversalStack seems fine when you don't need to do anything relative [per say] to the current URL. I almost always use URL generators, either absolute URL or in the case of the tags view I made I construct the joined URL in the view, so this hasn't affected me too much yet. But I'd certainly like to have the second option. The underlying tools are there, but knowing which traversal interface / adapter to apply isn't easy right now... Is __getitem__ enough? No one seems to have a good answer. IPublishTraverse? ITraversable? It seems like IPublishTraverse is the best one since it's from zope.publisher and not zope.app, and is specific to object / URL publishing. But that comes back to my dilemma: Is it cool to play with the traversal stack in publishTraverse? Why isn't 'furtherPath' part of the publishTraverse interface, but part of zope.app.traversing.interfaces.ITraversable's traverse? Why doesn't browser traversal seem to use zope.app...ITraversable? Oh man. Here it is, New Years Eve, I've got errands to run for my dog that I was going to go do an hour ago, yet here I sit consumed by an idea that I'd love to try but should put off to some other time. Basically it would be nice to specify a map... somehow.. for long URLs that are used to construct queries. A view object could use this map to match a URL piece by piece by traversing it one by one and making "proper" objects along the way that are locatable. When it gets to the end of the match, it could call a provided factory for that particular Map and pass in the matched URL since the start of the view as a list or mapping. This suite of tools could provide some map constructors that allow one to specify repeating path parts. The rest of the URL would still be in place, and maybe that final object could have more traversal happen after it, such as view getting. A quick example of what I'm thinking:
Re: [Zope3-Users] Specialized URL traversal.. Best way?
On Thu, Dec 29, 2005 at 11:22:28PM -0700, Jeff Shell wrote: > Again, this is to have URLs like: > > myapp/@@tags/zope/viewlet > > And turn that into a catalog search for anyof {'zope', 'viewlet'} > > def publishTraverse(self, request, name): > namestack = request.getTraversalStack() > if name not in namestack: > namestack.append(name) > namestack.reverse() > tags = tuple(namestack) > request.setTraversalStack([]) > > results = TaggedArticleFinder(self.__name__,self.__parent__,tags) > results.prepareSearch(request) > return results > > The 'TaggedArticleFinder' then provides an interface that a view can > be found for that displays the results. So I've got it all working > now... My coworker Albertas recently implemented something like this in SchoolTool (I've CCed him). Unfortunately it turned out to have some unforeseen consequences, for example, request.URL does not contain the path elements you "eat" manually, breaking self-posting forms (those that use ) and our login mechanism. > I was wondering - is this the best way to do this? Is there a better > recipe floating around out there? I would also like to know that. Marius Gedminas -- Any sufficiently advanced Operating System is indistinguishable from Linux. -- Jim Dennis signature.asc Description: Digital signature ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Specialized URL traversal.. Best way?
Jeff Shell wrote: > [snip] > > I was wondering - is this the best way to do this? Is there a better > recipe floating around out there? I appreciate Zope's direct-to-object > URL publishing (been using it since '97!), but custom URL maps past a > certain object like a view seem to be quite tricky, whereas Django and > generic toolkits like Routes are specializing in ways of managing > custom URL maps. I know there are a few places where one can take over > this process, but it's not obvious when and how to use them, or which > to use. BeforeTraversal event? publishTraverse? ITraversable? > ITraversing? Ultimately I'd like to put a couple of views into the > root of my app that can do something akin to Django's url_dispatch: > > http://www.djangoproject.com/documentation/url_dispatch/ > > where a set of patterns and a name are used to allow for various > dynamic queries. The name would be used to look up a component to > respond to the matched items in the path. It wouldn't interfere with > any other traversal (ie - wouldn't replace the default way of doing > it). Doing it from a browser view seems safest, since this is almost > exclusively about keeping nice URLs for web browsing. I just want to > know the best place to plug in. I don't have an answer, but I am also hoping to get some advice on the best way to get what in a Z2 PythonScript is called 'traverse_subpath'. Chris Withers and I were both asking about this back on Dec 15 in the "What's the rationale of @@?" thread (http://mail.zope.org/pipermail/zope3-users/2005-December/001684.html), but I didn't see an answer. Still haven't figured it out for myself, still hoping for some help. -- Wade Leftwich Ithaca, NY ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] Specialized URL traversal.. Best way?
This week I've been revisiting some of my early Zope 3 ideas in a small new application we plan to use internally. One of the core concepts of this system is 'tagging', similar to del.icio.us, flickr, snippets, etc. Old versions that I wrote managed tags manually, with a 'taglib' object and tags being their own indexes that manually tracked the documents that mentioned them. I wanted to use the catalog, but the required indexes weren't available or usable by me at the time, and then other projects came along. In the last version I wrote prior to now, I wrote a custom Traversable adapter for this 'taglib', which was BTreeContainer. zope.app.traversing.interfaces.ITraversable - traverse(name, furtherPath) I used 'furtherPath' to go along and turn paths like 'zope/enterprise/cms' into tags to search (again, using a manual system due to lack of catalog). Since this was on a custom container, it somehow worked. So today, I thought I could provide a similar adapter, but on a view object, that could get the rest of the requested path in one swoop that I could then use to query a SetIndex in the catalog. But no matter what I did, I couldn't get it to work. It doesn't seem like my ITraversable gets called at all for my view - even with that view providing the interface I say I adapt and on and on. I could get my traversable adapter from the interpreter, but it wasn't ever touched during the zope.publisher publication process. At best, I figured that 'publishTraverse()' was where I needed to go based on the errors that I kept having. But publishTraverse() deals with one name at a time... But it does pass in the request. And at most, I guessed that the traversal stack was what I needed. Again, this is to have URLs like: myapp/@@tags/zope/viewlet And turn that into a catalog search for anyof {'zope', 'viewlet'} def publishTraverse(self, request, name): namestack = request.getTraversalStack() if name not in namestack: namestack.append(name) namestack.reverse() tags = tuple(namestack) request.setTraversalStack([]) results = TaggedArticleFinder(self.__name__,self.__parent__,tags) results.prepareSearch(request) return results The 'TaggedArticleFinder' then provides an interface that a view can be found for that displays the results. So I've got it all working now... But it seems kindof awkward. There are a few different traversing options, and knowing which one applies when is difficult to figure out. And monkeying with the traversal stack.. Is that really what I should be doing here? It seems like the interface for ITraversable that specified 'furtherPath' is what I'd like to be using when I'm wanting to play with the whole path from this point on. I ultimately want to provide a few more options similar to this one for things like date based filtering (urls like @@bydate/2005/12 or 2005/12/29). None of these are containers or real objects, just URL segments used to construct a query. I was wondering - is this the best way to do this? Is there a better recipe floating around out there? I appreciate Zope's direct-to-object URL publishing (been using it since '97!), but custom URL maps past a certain object like a view seem to be quite tricky, whereas Django and generic toolkits like Routes are specializing in ways of managing custom URL maps. I know there are a few places where one can take over this process, but it's not obvious when and how to use them, or which to use. BeforeTraversal event? publishTraverse? ITraversable? ITraversing? Ultimately I'd like to put a couple of views into the root of my app that can do something akin to Django's url_dispatch: http://www.djangoproject.com/documentation/url_dispatch/ where a set of patterns and a name are used to allow for various dynamic queries. The name would be used to look up a component to respond to the matched items in the path. It wouldn't interfere with any other traversal (ie - wouldn't replace the default way of doing it). Doing it from a browser view seems safest, since this is almost exclusively about keeping nice URLs for web browsing. I just want to know the best place to plug in. ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users