# HG changeset patch # User Thierry Florac # Date 1610379922 -3600 # Node ID 2af30495d1d7684cb078b045a15dc318dd4f34a2 # Parent 22716baab0fec638bf42872a963dc7115f014092 Added aggregations support to views diff -r 22716baab0fe -r 2af30495d1d7 src/pyams_content/features/search/__init__.py --- a/src/pyams_content/features/search/__init__.py Tue Dec 01 09:19:16 2020 +0100 +++ b/src/pyams_content/features/search/__init__.py Mon Jan 11 16:45:22 2021 +0100 @@ -64,12 +64,15 @@ return True def get_results(self, context, sort_index=None, reverse=None, limit=None, - start=0, length=None, ignore_cache=False, get_count=False, request=None): + start=0, length=None, ignore_cache=False, get_count=False, request=None, + aggregates=None): if not ignore_cache: - request = check_request() + if request is None: + request = check_request() ignore_cache = bool(request.params) return super(SearchFolder, self).get_results(context, sort_index, reverse, limit, start, - length, ignore_cache, get_count, request) + length, ignore_cache, get_count, request, + aggregates) @adapter_config(context=ISearchFolder, provides=IFormContextPermissionChecker) @@ -143,3 +146,15 @@ Contains(index, ' and '.join((w + '*' for w in fulltext.split())))) yield Or(*query_params) + + +@adapter_config(name='content_type', context=SearchFolderQuery, provides=IViewUserQuery) +class SearchFolderContentTypeQuery(ContextAdapter): + """Search folder content-type query""" + + @staticmethod + def get_user_params(request): + content_type = request.params.get('content_type') + if content_type: + catalog = get_utility(ICatalog) + yield Eq(catalog['content_type'], content_type) diff -r 22716baab0fe -r 2af30495d1d7 src/pyams_content/features/search/portlet/__init__.py --- a/src/pyams_content/features/search/portlet/__init__.py Tue Dec 01 09:19:16 2020 +0100 +++ b/src/pyams_content/features/search/portlet/__init__.py Mon Jan 11 16:45:22 2021 +0100 @@ -19,8 +19,10 @@ from pyams_content import _ from pyams_content.features.search import ISearchFolder -from pyams_content.features.search.portlet.interfaces import ISearchResultsPortletSettings +from pyams_content.features.search.portlet.interfaces import IAggregatedPortletRenderer, \ + ISearchResultsPortletSettings from pyams_content.shared.view.interfaces import RELEVANCE_ORDER, VISIBLE_PUBLICATION_DATE_ORDER +from pyams_portal.interfaces import IPortletRendererSettings from pyams_portal.portlet import Portlet, PortletSettings, portlet_config from pyams_utils.factory import factory_config from pyams_utils.interfaces import VIEW_PERMISSION @@ -44,8 +46,7 @@ params = request.params return params.get('user_search', '').strip() - @staticmethod - def _get_items(request=None, start=0, length=10, limit=None, ignore_cache=False): + def _get_items(self, request=None, start=0, length=10, limit=None, ignore_cache=False): context = get_parent(request.context, ISearchFolder) if context is None: raise StopIteration @@ -57,6 +58,11 @@ if (order_by == RELEVANCE_ORDER) and \ not SearchResultsPortletSettings.has_user_query(request): request.GET['order_by'] = order_by = VISIBLE_PUBLICATION_DATE_ORDER + renderer_settings = IPortletRendererSettings(self) + if IAggregatedPortletRenderer.providedBy(renderer_settings): + aggregates = renderer_settings.aggregates + else: + aggregates = {} yield from context.get_results(context, order_by, reverse=order_by != RELEVANCE_ORDER, limit=limit, @@ -64,19 +70,20 @@ length=int(length), ignore_cache=ignore_cache, get_count=True, - request=request) + request=request, + aggregates=aggregates) def get_items(self, request=None, start=0, length=10, limit=None, ignore_cache=False): if not (self.allow_empty_query or self.has_user_query(request)): - yield from iter(((), 0), ) + yield from iter(((), 0, {}), ) else: check, items = tee( - SearchResultsPortletSettings._get_items(request, start, length, limit, - ignore_cache)) + self._get_items(request, start, length, limit, + ignore_cache)) try: next(check) except StopIteration: - yield from iter(((), 0), ) + yield from iter(((), 0, {}), ) else: yield from items diff -r 22716baab0fe -r 2af30495d1d7 src/pyams_content/features/search/portlet/interfaces.py --- a/src/pyams_content/features/search/portlet/interfaces.py Tue Dec 01 09:19:16 2020 +0100 +++ b/src/pyams_content/features/search/portlet/interfaces.py Mon Jan 11 16:45:22 2021 +0100 @@ -10,15 +10,24 @@ # FOR A PARTICULAR PURPOSE. # -__docformat__ = 'restructuredtext' - +from zope.interface import Attribute, Interface from zope.schema import Bool -from pyams_content import _ from pyams_i18n.schema import I18nTextLineField from pyams_portal.interfaces import IPortletSettings +__docformat__ = 'restructuredtext' + +from pyams_content import _ + + +class IAggregatedPortletRenderer(Interface): + """Search results portlet renderer with aggregations""" + + aggregates = Attribute("Search results aggregates") + + class ISearchResultsPortletSettings(IPortletSettings): """Search results portlet settings""" diff -r 22716baab0fe -r 2af30495d1d7 src/pyams_content/features/search/portlet/zmi/templates/search-preview.pt --- a/src/pyams_content/features/search/portlet/zmi/templates/search-preview.pt Tue Dec 01 09:19:16 2020 +0100 +++ b/src/pyams_content/features/search/portlet/zmi/templates/search-preview.pt Mon Jan 11 16:45:22 2021 +0100 @@ -1,6 +1,6 @@
+ (items, count, aggregations) settings.get_items(request, limit=10, ignore_cache=True);"> ${i18n:settings.title}
diff -r 22716baab0fe -r 2af30495d1d7 src/pyams_content/shared/view/__init__.py --- a/src/pyams_content/shared/view/__init__.py Tue Dec 01 09:19:16 2020 +0100 +++ b/src/pyams_content/shared/view/__init__.py Mon Jan 11 16:45:22 2021 +0100 @@ -111,8 +111,9 @@ return list(data_types) def get_results(self, context, sort_index=None, reverse=None, limit=None, - start=0, length=999, ignore_cache=False, get_count=False, request=None): - results, count = _MARKER, 0 + start=0, length=999, ignore_cache=False, get_count=False, request=None, + aggregates=None): + results, count, aggregations = _MARKER, 0, {} if not ignore_cache: # check for cache views_cache = get_cache(VIEWS_CACHE_REGION, VIEWS_CACHE_NAME) @@ -124,6 +125,7 @@ try: results = views_cache.get_value(cache_key) count = views_cache.get_value(cache_key + '::count') + aggregations = views_cache.get_value(cache_key + '::aggregations') except KeyError: pass # Execute query @@ -136,22 +138,25 @@ if not sort_index: sort_index = self.order_by # Get query results - results, count = adapter.get_results(context, - sort_index, - reverse if reverse is not None else self.reversed_order, - limit or self.limit, - request=request) + results, count, aggregations = adapter.get_results(context, + sort_index, + reverse if reverse is not None + else self.reversed_order, + limit or self.limit, + request=request, + aggregates=aggregates) count = min(count, limit or self.limit or 999) cache, results = tee(islice(results, start, start + length)) if not ignore_cache: intids = get_utility(IIntIds) views_cache.set_value(cache_key, [intids.queryId(item) for item in cache]) views_cache.set_value(cache_key + '::count', count) + views_cache.set_value(cache_key + '::aggregations', aggregations) logger.debug("Storing view items to cache key {0}".format(cache_key)) else: results = CatalogResultSet(results) logger.debug("Retrieving view items from cache key {0}".format(cache_key)) - return (results, count) if get_count else results + return (results, count, aggregations) if get_count else results register_content_type(WfView, shared_content=False) @@ -215,7 +220,8 @@ filters &= Any(catalog['data_type'], data_types) return params - def get_results(self, context, sort_index, reverse, limit, request=None): + def get_results(self, context, sort_index, reverse, limit, + request=None, aggregates=None): view = self.context catalog = get_utility(ICatalog) registry = get_current_registry() @@ -235,7 +241,7 @@ for name, adapter in sorted(registry.getAdapters((view,), IViewQueryFilterExtension), key=lambda x: x[1].weight): items = adapter.filter(context, items, request) - return unique_iter(items), total_count + return unique_iter(items), total_count, {} @subscriber(IObjectModifiedEvent, context_selector=IWfView) diff -r 22716baab0fe -r 2af30495d1d7 src/pyams_content/shared/view/interfaces.py --- a/src/pyams_content/shared/view/interfaces.py Tue Dec 01 09:19:16 2020 +0100 +++ b/src/pyams_content/shared/view/interfaces.py Mon Jan 11 16:45:22 2021 +0100 @@ -154,7 +154,8 @@ def get_params(self, context, request=None): """Get static view query params""" - def get_results(self, context, sort_index, reverse, limit, request=None): + def get_results(self, context, sort_index, reverse, limit, + request=None, aggregates=None): """Get tuple of limited results and total results count"""