From 9043c0459ec25153bc7fcf18c29201893a1ed5f0 Mon Sep 17 00:00:00 2001 From: helmutm Date: Mon, 17 Mar 2008 09:36:51 +0000 Subject: [PATCH] allow view parameters for view names as node attributes to make views more selective git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@2458 fd906abe-77d9-0310-91a1-e0d9ade77398 --- README.txt | 20 ++++++++++++++++++++ browser/common.py | 13 +++++++++++++ browser/concept.py | 18 +++++++++++++++++- browser/node.py | 36 ++++++++++++++++++++++++++---------- 4 files changed, 76 insertions(+), 11 deletions(-) diff --git a/README.txt b/README.txt index 5118104..9338387 100755 --- a/README.txt +++ b/README.txt @@ -814,6 +814,26 @@ target object's view here: 'http://127.0.0.1/loops/views/m1/m11/m111/.target23' +Special views +------------- + +We may set a special view for a node by providing a view name. + + >>> from loops.browser.node import ListChildren + >>> component.provideAdapter(ListChildren, (INode, IBrowserRequest), Interface, + ... name='listchildren') + + >>> m112.viewName = 'listchildren?types=person' + >>> view = NodeView(m112, TestRequest()) + + >>> targetView = view.view + + >>> targetView.macroName + 'listchildren' + + >>> targetView.params + {'types': ['person']} + Collecting Information about Parents ==================================== diff --git a/browser/common.py b/browser/common.py index 051c734..adc9b4f 100644 --- a/browser/common.py +++ b/browser/common.py @@ -22,6 +22,7 @@ Common base class for loops browser view classes. $Id$ """ +from cgi import parse_qs from zope import component from zope.app.form.browser.interfaces import ITerms from zope.app.i18n.interfaces import ITranslationDomain @@ -126,6 +127,18 @@ class BaseView(GenericView, I18NView): # allow for having a separate object the view acts upon return self.context + @Lazy + def params(self): + result = {} + paramString = self.request.annotations.get('loops.view', {}).get('params') + if paramString: + result = parse_qs(paramString) + for k, v in result.items(): + if len(v) == 1: + v = [x.strip() for x in v[0].split(',')] + result[k] = v + return result + def setSkin(self, skinName): skin = None if skinName and IView.providedBy(self.context): diff --git a/browser/concept.py b/browser/concept.py index 0097b29..188c383 100644 --- a/browser/concept.py +++ b/browser/concept.py @@ -266,12 +266,19 @@ class ConceptView(BaseView): def getChildren(self, topLevelOnly=True, sort=True): cm = self.loopsRoot.getConceptManager() hasType = cm.getTypePredicate() + params = self.params + criteria = {} + if params.get('types'): + criteria['types'] = [cm.get(name) for name in params['types']] standard = cm.getDefaultPredicate() rels = (self.childViewFactory(r, self.request, contextIsSecond=True) for r in self.context.getChildRelations(sort=None)) if sort: rels = sorted(rels, key=lambda r: (r.order, r.title.lower())) for r in rels: + if criteria: + if not self.checkCriteria(r, criteria): + continue if topLevelOnly and r.predicate == hasType: # only show top-level entries for type instances: skip = False @@ -279,9 +286,18 @@ class ConceptView(BaseView): if parent.conceptType == self.context: skip = True break - if skip: continue + if skip: + continue yield r + def checkCriteria(self, relation, criteria): + result = True + for k, v in criteria.items(): + if k == 'types': + v = [item for item in v if item is not None] + result = result and (relation.context.conceptType in v) + return result + # Override in subclass to control what is displayd in listings: children = getChildren diff --git a/browser/node.py b/browser/node.py index 6aa1d67..7f8f4ff 100644 --- a/browser/node.py +++ b/browser/node.py @@ -110,10 +110,15 @@ class NodeView(BaseView): @Lazy def view(self): - viewName = self.request.get('loops.viewName') or self.context.viewName - if viewName: + name = self.request.get('loops.viewName', '') or self.context.viewName + if '?' in name: + name, params = name.split('?', 1) + ann = self.request.annotations.get('loops.view', {}) + ann['params'] = params + self.request.annotations['loops.view'] = ann + if name: adapter = component.queryMultiAdapter( - (self.context, self.request), name=viewName) + (self.context, self.request), name=name) if adapter is not None: return adapter return self @@ -298,16 +303,22 @@ class NodeView(BaseView): return None def targetView(self, name='index.html', methodName='show'): + if '?' in name: + name, params = name.split('?', 1) + print '***', name, params target = self.virtualTargetObject if target is not None: ti = IType(target).typeInterface - targetView = None - if ti is not None: - adapted = ti(target) - targetView = component.queryMultiAdapter((adapted, self.request), - name=name) - if targetView is None: - targetView = component.getMultiAdapter((target, self.request), + #targetView = None + #if ti is not None: + # adapted = ti(target) + # targetView = component.queryMultiAdapter((adapted, self.request), + # name=name) + #if targetView is None: + # targetView = component.getMultiAdapter((target, self.request), + # name=name) + target = adapted(target) + targetView = component.getMultiAdapter((target, self.request), name=name) if name == 'index.html' and hasattr(targetView, 'show'): return targetView.show() @@ -537,12 +548,17 @@ class SpecialNodeView(NodeView): class ListPages(SpecialNodeView): + macroName = 'listpages' + class ListResources(SpecialNodeView): + macroName = 'listresources' + class ListChildren(SpecialNodeView): + macroName = 'listchildren'