[Grok-dev] Traverser, Request and URL mess

Martijn Faassen faassen at startifact.com
Sat Oct 10 09:37:33 EDT 2009


Hey Souheil,

Souheil CHELFOUH wrote:

> I'm currently working on grokui.base and grokui.admin
> With Uli, we decided to use a namespace for the views, to get a cleaner base.

Thanks very much for doing this work!

> Everything is working nicely. The views are registered for a skin
> layer, the skin is applied on traversal by a namespace traverser,
> ++grokui++.

> However, when an application is created, we'd like to be
> able to acces its URL without having the traverser ++grokui++ added in
> the request. I couldn't find an easy way to do that without
> duplicating the request and modifying the _app_names. 

We're talking about the ability to generate a URL to something in 
another skin, correct? I.e. to generate a link to the application's URL, 
and the application is *not* in the admin UI skin of course. The other 
situation where this happens would be if you would want the root of the 
site to redirect to the admin UI (which is in the ++grokui++ skin). But 
we have the added complexity that ++grokui++ is its own namespace here, 
instead of ++skin++grokui.

> I found 2
> solutions for that :
> 
> # This is totaly ugly, but it works without much effort :)
> url = absoluteURL(application, request).replace('/++grokui++', '')

I think this is safe enough. It's ugly, but it has the virtue of being 
short.

> # This is nicer, but maybe there's another solution :
> class GrokUINamespace(grok.MultiAdapter):
>     grok.name('grokui')
>     grok.provides(ITraversable)
>     grok.adapts(IRootFolder, browser.IBrowserRequest)
> 
>     def __init__(self, context, request):
>         self.context = context
> 
>         annotations = IAnnotations(request)
>         grokui_info = annotations.get('grokui', None)
>         if grokui_info is None:
>             grokui_info = annotations['grokui'] = {}
>         # we get the root url before the ++grokui++ is shifted
>         # and use this URL to compute the application one
>         grokui_info['root_url'] = request.getApplicationURL()
> 
>         applySkin(self.request, GrokUISkin)
>         request.shiftNameToApplication()
> 
>     def traverse(self, name, ignore):
>         return self.context

> Anyone could help me, with any kind of trick/tip/opinion ?
> The second solution works and is much nicer than the first one, but it
> looks a bit hackish.

Could you explain to me why you think the second solution is nicer? I 
have a hard time even understand what could possibly be going on...
I don't think this is nicer, as it's totally complicated and it's hard 
for me to understand what is going on. :) What *is* this doing?

If the problem indeed is about the ability to generate URLs to other 
skins, this is a long-standing discussion with no conclusion. The story 
appears to me that:

* we keep running into it

* it appears hard to devise a general solution

Since we keep runnign into it, perhaps we can come up with a more 
limited solution, where it's at least possible to create URLs *without* 
any ++skin++ bit in it, or to at least add ++skin++foo easily to an 
existing URL (somewhere in the beginning). That won't cover all cases 
(virtual hosts, namespaces not appearing at the root of the URL, other 
things?) but it would cover a lot of them. We also need to make sure we 
can handle your case, where instead of ++skin++foo, you just want ++foo++.

Perhaps we need an API like this:

self.url(..., namespace=('skin', 'foo')

to go to ++skin++foo

and:

self.url(..., namespace=('grokui',None)

to go to ++grokui++

and:

self.url(..., namespace=(None, None))

to have no special namespace.

the default would have namespace be None and it'd always generate URLs 
within the same namespace then. This is what it does already.

I think it would probably simplest to make this work by simple but 
well-tested string rewriting.

Regards,

Martijn



More information about the Grok-dev mailing list