[Grok-dev] a "skin" keyword argument to view.url() method
Christian Klinger
cklinger at novareto.de
Tue Nov 20 11:44:19 UTC 2012
Hi JW,
+1 implementation looks ok.
Cheers Christian
Jan-Jaap Driessen schrieb:
> This is very useful to me too, but hey, we share a desk :)
>
> +1
>
>
> On Tue, Nov 20, 2012 at 11:33 AM, Jan-Wijbrand Kolman
> <janwijbrand at gmail.com <mailto:janwijbrand at gmail.com>> wrote:
>
> Hi,
>
> In the application we develop we regularly need to compute URLs for a
> specific skin. We have some helper functions for that, but I guess
> having this functionality as part of the ``view.url()`` method could be
> generally useful.
>
> Below you will find a diff between the current grokcore.view trunk and
> the jw-urls-with-skin branch I created to implement this feature.
>
> Please tell me if you think this feature is indeed generally useful and
> whether you'd agree with my implementation. Thx!
>
> regards, jw
>
>
> Index: src/grokcore/view/util.py
> ===================================================================
> --- src/grokcore/view/util.py (.../trunk) (revision 128365)
> +++ src/grokcore/view/util.py (.../branches/jw-urls-with-skin)
> (revision
> 128365)
> @@ -14,18 +14,37 @@
> """Grok utility functions.
> """
> import urllib
> +import urlparse
> from grokcore.security.util import check_permission
> from zope.component import getMultiAdapter
> from zope.security.checker import NamesChecker, defineChecker
> from zope.traversing.browser.absoluteurl import _safe as
> SAFE_URL_CHARACTERS
> from zope.traversing.browser.interfaces import IAbsoluteURL
>
> +import directive
>
> -def url(request, obj, name=None, data=None):
> +ASIS = object()
> +
> +def url(request, obj, name=None, skin=ASIS, data=None):
> url = getMultiAdapter((obj, request), IAbsoluteURL)()
> if name is not None:
> url += '/' + urllib.quote(name.encode('utf-8'),
> SAFE_URL_CHARACTERS)
>
> + if skin is not ASIS:
> + # Remove whatever ``++skin++[name]`` is active.
> + parts = list(urlparse.urlparse(url))
> + path = parts[2]
> + if path.startswith('/++skin++'):
> + # Find next / in the path.
> + idx = path.find('/', 1)
> + path = path[idx:]
> + if skin is not None:
> + # If a skin is set, add ``++skin++`` as the leading path
> segment.
> + name = directive.skin.bind().get(skin)
> + path = '/++skin++%s%s' % (name, path)
> + parts[2] = path
> + url = urlparse.urlunparse(parts)
> +
> if not data:
> return url
>
> Index: src/grokcore/view/ftests/url/url.py
> ===================================================================
> --- src/grokcore/view/ftests/url/url.py (.../trunk) (revision
> 128365)
> +++ src/grokcore/view/ftests/url/url.py
> (.../branches/jw-urls-with-skin) (revision 128365)
> @@ -171,6 +171,45 @@
> >>> browser.contents
> '11'
>
> +It is possible to compute URLs for specific skin names.
> +
> +First show how a view registered for a view, will by default
> compute URLs
> +for that skin:
> +
> + >>>
> browser.open('http://127.0.0.1/++skin++urltesting/herd/manfred/@@test')
> + >>> browser.contents
> + "I'm on a url testing skin:
> + http://127.0.0.1/++skin++urltesting/herd/manfred/test"
> +
> +We get the views manually so we can do a greater variety of url()
> calls:
> +
> + >>> from zope.publisher.browser import applySkin
> + >>> request = TestRequest()
> + >>> applySkin(request, URLTestingSkin)
> + >>> # Shifting names normally happens during URL traversal.
> + >>> request._traversed_names = ['++skin++urltesting']
> + >>> request.shiftNameToApplication()
> + >>> index_view = component.getMultiAdapter((manfred, request),
> name='test')
> + >>> index_view.url()
> + 'http://127.0.0.1/++skin++urltesting/herd/manfred/test'
> +
> +Explicitely remove the skin part:
> +
> + >>> index_view.url(skin=None)
> + 'http://127.0.0.1/herd/manfred/test'
> +
> +Use another skin:
> +
> + >>> index_view.url(skin=AnotherURLTestingSkin)
> + 'http://127.0.0.1/++skin++anotherurltesting/herd/manfred/test'
> +
> +Use something that is not a skin will fail:
> +
> + >>> index_view.url(skin='foobar')
> + Traceback (most recent call last):
> + ...
> + AttributeError: 'str' object has no attribute 'queryTaggedValue'
> +
> """
> import grokcore.view as grok
> from zope.container.contained import Contained
> @@ -199,3 +238,16 @@
> return unicode(self.age * 2)
>
> yetanother = grok.PageTemplate('<p tal:replace="view/url" />')
> +
> +class URLTestingSkin(grok.IBrowserRequest):
> + grok.skin('urltesting')
> +
> +class AnotherURLTestingSkin(grok.IBrowserRequest):
> + grok.skin('anotherurltesting')
> +
> +class URLTestingViewOnASkin(grok.View):
> + grok.layer(URLTestingSkin)
> + grok.name <http://grok.name>('test')
> +
> + def render(self):
> + return u"I'm on a url testing skin: %s" % self.url()
> Index: src/grokcore/view/components.py
> ===================================================================
> --- src/grokcore/view/components.py (.../trunk) (revision
> 128365)
> +++ src/grokcore/view/components.py (.../branches/jw-urls-with-skin)
> (revision 128365)
> @@ -78,7 +78,7 @@
> return self.request.response.redirect(
> url, status=status, trusted=trusted)
>
> - def url(self, obj=None, name=None, data=None):
> + def url(self, obj=None, name=None, skin=util.ASIS, data=None):
> """Return string for the URL based on the obj and name.
>
> If no arguments given, construct URL to view itself.
> @@ -91,6 +91,16 @@
> If both object and name arguments are supplied, construct URL
> to `obj/name`.
>
> + Optionally pass a `skin` keyword argument. This should be a
> + skin component and the skin's name is taken from this
> + component. The effect of this argument is a leading
> + ``++skin++[skinname]/`` segment in the path-part of the URL.
> + When the argument is not passed, whatever skin is currently set
> + on the request will be effective in the URL.
> +
> + When passing ``None`` whatever skin is currently effective will
> + be removed from the URLs.
> +
> Optionally pass a `data` keyword argument which gets added to
> the URL as a CGI query string.
>
> @@ -110,7 +120,7 @@
> # create URL to view on context
> obj = self.context
>
> - return util.url(self.request, obj, name, data)
> + return util.url(self.request, obj, name, skin, data)
>
>
> _______________________________________________
> Grok-dev mailing list
> Grok-dev at zope.org <mailto:Grok-dev at zope.org>
> https://mail.zope.org/mailman/listinfo/grok-dev
>
>
> _______________________________________________
> Grok-dev mailing list
> Grok-dev at zope.org
> https://mail.zope.org/mailman/listinfo/grok-dev
More information about the Grok-dev
mailing list