The groupby modifiers take a bit more effort to understand but are necessary to get some things
working. As a full example, this is the code for the groupby modifiers for the screenshot above.
there are 2 indexes: classifier_themes that feeds the locations list (bekkens) and classifier_categories (parameters) that contains pollutants.
the categories is a 2 level one, but the as @MrTango mentioned to make selections it's flattened to keywords/strings. The trick is to include al sub levels as well.
So an item that has 'drukken > stikstof' is twice in the index, one for key of top level 'drukken' and for for key 'drukken > stikstof'
I can't remember if I made this one up myself, most likely is I copied/adapted something, but I'm using a helper class to create the groupby modifier where I pass in the vocabulary that is already available for my two indexes by collective.classifiers, collective.taxonomy will likely also make vocabularies available? It demonstrates using the display modifier and the sorting.
<adapter factory=".collectionfilter.groupby_modifier" name="modifier_1" />
does the zcml registration.
from collective.collectionfilter.interfaces import IGroupByCriteria
from collective.collectionfilter.interfaces import IGroupByModifier
from zope.component import adapter, getUtility
from zope.interface import implementer, provider
from zope.schema.interfaces import IVocabularyFactory
from zope.schema.interfaces import IContextAwareDefaultFactory
from zope.component.hooks import getSite
import logging
logger = logging.getLogger("sgbp.content")
class VocabularyLookup(object):
vocabulary = None
flatten = False
def clean_title(self, term):
result = term.title.split(" > ", 1)
if len(result) > 1:
return result[-1]
elif len(result) == 1:
return term.title
def __init__(self, vocab, flatten=False, context=None):
factory = getUtility(IVocabularyFactory, vocab)
if not context:
self.vocabulary = factory(getSite())
else:
self.vocabulary = factory(context)
self.flatten = flatten
self.terms = [
self.clean_title(term) if flatten else term.title
for term in self.vocabulary._terms
]
self.sort_map = dict([(term[1], term[0]) for term in enumerate(self.terms)])
def display(self, value):
try:
term = self.vocabulary.getTerm(value)
except LookupError:
logger.warn(
"Could not find '{0}' in vocabulary {1}".format(value, self.vocabulary)
)
return value
if self.flatten:
return self.clean_title(term)
return term.title
def sortmap(self, value):
val = value["title"]
return self.sort_map.get(val, 0)
@implementer(IGroupByModifier)
@adapter(IGroupByCriteria)
def groupby_modifier(groupby):
themes_label = VocabularyLookup("collective.classifiers.themes", flatten=True)
categories_label = VocabularyLookup(
"collective.classifiers.categories", flatten=False
)
groupby._groupby["classifiers_themes"] = {
"index": "classifiers_themes",
"metadata": "classifiers_themes",
"display_modifier": themes_label.display,
"sort_key_function": themes_label.sortmap,
# "value_blacklist": ["bekkens", "grondwatersystemen"],
}
groupby._groupby["classifiers_categories"] = {
"index": "classifiers_categories",
"metadata": "classifiers_categories",
"display_modifier": categories_label.display,
"sort_key_function": categories_label.sortmap,
}