[Checkins] SVN: grokcore.view/branches/jw-urls-with-skin/src/grokcore/view/ Do not pass a skin name, but a skin component to the url() method. The

Jan Wijbrand Kolman cvs-admin at zope.org
Tue Nov 20 10:26:06 UTC 2012


Log message for revision 128365:
  Do not pass a skin name, but a skin component to the url() method. The
  skin name is taken from this component.
  
  

Changed:
  U   grokcore.view/branches/jw-urls-with-skin/src/grokcore/view/components.py
  U   grokcore.view/branches/jw-urls-with-skin/src/grokcore/view/ftests/url/url.py
  U   grokcore.view/branches/jw-urls-with-skin/src/grokcore/view/util.py

-=-
Modified: grokcore.view/branches/jw-urls-with-skin/src/grokcore/view/components.py
===================================================================
--- grokcore.view/branches/jw-urls-with-skin/src/grokcore/view/components.py	2012-11-20 10:16:33 UTC (rev 128364)
+++ grokcore.view/branches/jw-urls-with-skin/src/grokcore/view/components.py	2012-11-20 10:26:06 UTC (rev 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)
 
 
 class View(ViewSupport, BrowserPage):

Modified: grokcore.view/branches/jw-urls-with-skin/src/grokcore/view/ftests/url/url.py
===================================================================
--- grokcore.view/branches/jw-urls-with-skin/src/grokcore/view/ftests/url/url.py	2012-11-20 10:16:33 UTC (rev 128364)
+++ grokcore.view/branches/jw-urls-with-skin/src/grokcore/view/ftests/url/url.py	2012-11-20 10:26:06 UTC (rev 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('test')
+
+    def render(self):
+        return u"I'm on a url testing skin: %s" % self.url()

Modified: grokcore.view/branches/jw-urls-with-skin/src/grokcore/view/util.py
===================================================================
--- grokcore.view/branches/jw-urls-with-skin/src/grokcore/view/util.py	2012-11-20 10:16:33 UTC (rev 128364)
+++ grokcore.view/branches/jw-urls-with-skin/src/grokcore/view/util.py	2012-11-20 10:26:06 UTC (rev 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
 



More information about the checkins mailing list