[Twisted-Python] resource navigation

Donovan Preston dp at twistedmatrix.com
Fri Oct 10 09:56:02 MDT 2003


On Oct 9, 2003, at 6:01 PM, Syver Enstad wrote:

>
> Let's say I have a hierarchy of resources like this:
>
> grandparent
>   parent1
>   parent2
>      child1
>      child2
>         grandchild
>
> Is there an easy way to know at runtime what url goes to let's say
> parent2? I am interested primarily because I am interested in having
> as self contained page classes as possible and hardcoding links to
> parent2 in grandchilds view template seems brittle.

Indeed. I have been experimenting with techniques for making all the 
Resource subclasses in a resource tree ignorant of each other for a 
while. One useful technique, if your path segments have meaningful 
names, is to simply use request.prepath to build a view of links 
leading to the current object (or "breadcrumbs"):

def wvupdate_breadcrumbs(self, request, widget, data):
	l = lmx(widget)
	fullpath = '/' # let us assume our application is installed at the 
root of the webserver
	for pathsegment in request.prepath:
		fullpath += pathsegment + '/'
		l.a(href= fullpath).text(pathsegment)

But this is only useful for rendering immediate ancestors, and also the 
only text you can put in the anchor tag is the actual pathsegment which 
shows up in the URL.

> Woven seems to be strangely symetric regarding models and pages. An
> example is getChild / getSubmodel and on top of that wchild_ /
> wmfactory_. The woven model framwork supports asking parents of a
> model if a submodel name can't be found, it might be interesting to
> have something similar for resources so that one can have link's on a
> child page that will be resolved by the parent.

Woven models keep track of the parents they were looked up from using 
IModel wrappers, but Resources, being a significantly older API, do 
not. As I mentioned above, I have been experimenting with techniques in 
this area recently, and one of the ideas I have come up with is in 
Quotient. (Note that while the code is in Quotient, nothing actually 
uses it yet.)

To use this technique, you have to control getChild (or you could 
rewrite getChildForRequest -- but that's an exercise for the reader). 
The idea is to gather a list of all the objects that had a getChild 
called on them for a given request. Here's the trick:

class IObjectCrumbs(components.Interface):
     """An interface on the request which keeps track of the list
     objects that were involved in the url traversal process
     for this request.
     """

components.registerAdapter(lambda _: [], server.Request, IObjectCrumbs)

class MyPageSubclass(page.LivePage):
     def getChild(self, name, request):
         rv = page.LivePage.getChild(self, name, request) # substitute 
Page if you aren't using LivePage
         if name != '' or request.prepath == ['']:
             IObjectCrumbs(request).append(rv)
         return rv

Once you have installed this getChild on all of the Resource objects 
involved in your application's Resource tree, you can then at any point 
in the render process get an IObjectCrumbs adapter on the request to 
get the list of actual instances which correspond with the path 
segments in request.prepath. What you do with them is then up to you; 
the most obvious things that come to mind are asking the instances to 
render a nicely formatted anchor instead of using the pathsegment text 
in the breadcrumbs example above, and introspecting the instances to 
see which child names they are capable of rendering (which you will 
have to do in a fairly application-specific manner; because of 
getChild, it isn't possible to write a general solution which lists all 
valid child names for a given resource).

I'm still trying to find the best solution to this problem in Quotient, 
and it would be really great if we could get it to the point where we 
could provide a Widget which anyone could drop into any Page anywhere 
in the Resource tree, and it would render a nice tree of links the user 
can use to navigate, but we're probably quite a ways off from actually 
being able to do that in a sane manner.

dp





More information about the Twisted-Python mailing list