changeset 1092:63ed5f6bd4eb

pages: new "getURLByPath" method in LiberviaPage, which is similar to getURLByNames, but which a more readable way to request a path with named pages.
author Goffi <goffi@goffi.org>
date Fri, 01 Jun 2018 12:58:20 +0200
parents 092e910292c9
children eda7a1c6532a
files src/server/pages.py src/server/utils.py
diffstat 2 files changed, 53 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/server/pages.py	Fri Jun 01 12:56:13 2018 +0200
+++ b/src/server/pages.py	Fri Jun 01 12:58:20 2018 +0200
@@ -31,7 +31,7 @@
 log = getLogger(__name__)
 from libervia.server.constants import Const as C
 from libervia.server import session_iface
-from libervia.server.utils import quote
+from libervia.server.utils import quote, SubPage
 import libervia
 
 from collections import namedtuple
@@ -452,16 +452,19 @@
             current_url = current_url + u'?' + encoded
         return current_url
 
-    def getSubPageByName(self, page, subpage_name):
+    def getSubPageByName(self, subpage_name, parent=None):
         """retrieve a subpage and its path using its name
 
-        @param request(server.Request): current HTTP request
-        @param page_name(unicode): name of the page to retrieve
-            it must be a direct children of current page
+        @param subpage_name(unicode): name of the sub page
+            it must be a direct children of parent page
+        @param parent(LiberviaPage, None): parent page
+            None to use current page
         @return (tuple[str, LiberviaPage]): page subpath and instance
         @raise exceptions.NotFound: no page has been found
         """
-        for path, child in page.children.iteritems():
+        if parent is None:
+            parent = self
+        for path, child in parent.children.iteritems():
             try:
                 child_name = child.name
             except AttributeError:
@@ -488,10 +491,10 @@
         @param page_name(unicode): name of the page to retrieve
             it must be a direct children of current page
         @param *args(list[unicode]): arguments to add as path elements
-        @return unicode: absolute URL to the sub page
+        @return (unicode): absolute URL to the sub page
         """
         current_url = self.getCurrentURL(request)
-        path, child = self.getSubPageByName(self, page_name)
+        path, child = self.getSubPageByName(page_name)
         return os.path.join(u'/', current_url, path, *[quote(a) for a in args])
 
     def getURLByNames(self, named_path):
@@ -511,12 +514,49 @@
                 current_page = self.getPageByName(page_name)
                 path.append(current_page.getURL(*page_args))
             else:
-                sub_path, current_page = self.getSubPageByName(current_page, page_name)
+                sub_path, current_page = self.getSubPageByName(page_name, parent=current_page)
                 path.append(sub_path)
                 if page_args:
                     path.extend([quote(a) for a in page_args])
         return self.host.checkRedirection(u'/'.join(path))
 
+    def getURLByPath(self, *args):
+        """generate URL by path
+
+        this method as a similar effect as getURLByNames, but it is more readable
+        by using SubPage to get pages instead of using tuples
+        @param *args: path element:
+            - if unicode, will be used as argument
+            - if util.SubPage instance, must be the name of a subpage
+        @return (unicode): generated path
+        """
+        args = list(args)
+        if not args:
+            raise ValueError('You must specify path elements')
+        # root page is the one needed to construct the base of the URL
+        # if first arg is not a SubPage instance, we use current page
+        if not isinstance(args[0], SubPage):
+            root = self
+        else:
+            root = self.getPageByName(args.pop(0))
+        # we keep track of current page to check subpage
+        current_page = root
+        url_elts = []
+        arguments = []
+        while True:
+            while args and not isinstance(args[0], SubPage):
+                arguments.append(quote(args.pop(0)))
+            if not url_elts:
+                url_elts.append(root.getURL(*arguments))
+            else:
+                url_elts.extend(arguments)
+            if not args:
+                break
+            else:
+                path, current_page = current_page.getSubPageByName(args.pop(0))
+                arguments = [path]
+        return self.host.checkRedirection(u'/'.join(url_elts))
+
     def getChildWithDefault(self, path, request):
         # we handle children ourselves
         raise exceptions.InternalError(u"this method should not be used with LiberviaPage")
--- a/src/server/utils.py	Fri Jun 01 12:56:13 2018 +0200
+++ b/src/server/utils.py	Fri Jun 01 12:58:20 2018 +0200
@@ -97,3 +97,7 @@
         handler_data[u'error'] = error_cb
         handler_data[u'timeout'] = reactor.callLater(timeout, self._timeout)
         return deferred
+
+
+class SubPage(unicode):
+    """use to mark subpages when generating a page path"""