I have a dexterity object 'release' which have a parent dexterity object 'project'. I created a portal_catalog search for new releases which have the review state 'final' and display them. I let the user choose the review state of the release. But I don't want to show releases to the public where the review state of their project is not 'published'. Thus I need a switch in my query (or in the function that contains this query) to filter out releases with parents that are not published yet.
My current function is the following:
def get_latest_releases(self):
self.catalog =api.portal.get_tool(name='portal_catalog')
sort_on = 'created'
contentFilter = {'sort_on' : sort_on,
'sort_order' : 'reverse',
'review_state' : 'final',
'portal_type' : (' ' ),
}
a simple solution would be to iterate over releases and check if their project is published
(caution: i did not test/verify this pseudo code)
from Acquisition import aq_parent
from plone import api
result = []
releases = api.content.find(portal_type='release', review_state='final', sort...)
for brain in releases:
release = brain.getObject() # this might be a performance hit if iterating over hundreds or thousands of releases
if api.content.get_state(aq_parent(release)) == 'published':
result.append(release)
# result now contains all releases located in a published project
this should be straight forward and not a big performance deal. if you have thousands of releases to iterate over (and can't use pagination and yield) you can alternatively search for published projects first and then limit the search for releases to these projects (works if projects can't be nested)
published_projects = api.content.find(portal_type='project', review_state='published')
# filter by path (multiple paths should work, did not test)
published_paths = [brain.getPath() for brain in published_projects]
release_brains = api.content.find(portal_type='release', path=published_paths, review_state='final')
#filter by uid
release_uids = []
for brain in published_projects:
project = brain.getObject()
release_uids += [brain.UID for brain in api.content.find(context=project, portal_type='release')]
releases = api.content.find(UID=release_uids, review_state='final', sort...)
Post-filtering is option as explained.
Another option would be to create a custom index and a custom indexer that would index the state of both objects together in order to query without loading the full objects from the brains.