def get_projects_for_macro(category=None, display_mode='grid', sort='last_updated', show_total=False, limit=100, labels='', award='', private=False, columns=1, show_proj_icon=True, show_download_button=True, show_awards_banner=True, grid_view_tools='', initial_q={}): from allura.lib.widgets.project_list import ProjectList from allura.lib import utils from allura import model as M # 'trove' is internal substitution for 'category' filter in wiki macro trove = category limit = int(limit) q = dict( deleted=False, is_nbhd_project=False) q.update(initial_q) if labels: or_labels = labels.split('|') q['$or'] = [{'labels': {'$all': l.split(',')}} for l in or_labels] if trove is not None: trove = M.TroveCategory.query.get(fullpath=trove) if award: aw = M.Award.query.find(dict( created_by_neighborhood_id=c.project.neighborhood_id, short=award)).first() if aw: ids = [grant.granted_to_project_id for grant in M.AwardGrant.query.find(dict( granted_by_neighborhood_id=c.project.neighborhood_id, award_id=aw._id))] if '_id' in q: ids = list(set(q['_id']['$in']).intersection(ids)) q['_id'] = {'$in': ids} if trove is not None: q['trove_' + trove.type] = trove._id sort_key, sort_dir = 'last_updated', pymongo.DESCENDING if sort == 'alpha': sort_key, sort_dir = 'name', pymongo.ASCENDING elif sort == 'random': sort_key, sort_dir = None, None elif sort == 'last_registered': sort_key, sort_dir = '_id', pymongo.DESCENDING elif sort == '_id': sort_key, sort_dir = '_id', pymongo.DESCENDING projects = [] if private: # Only return private projects. # Can't filter these with a mongo query directly - have to iterate # through and check the ACL of each project. for chunk in utils.chunked_find(M.Project, q, sort_key=sort_key, sort_dir=sort_dir): projects.extend([p for p in chunk if p.private]) total = len(projects) if sort == 'random': projects = random.sample(projects, min(limit, total)) else: projects = projects[:limit] else: total = None if sort == 'random': # MongoDB doesn't have a random sort built in, so... # 1. Do a direct pymongo query (faster than ORM) to fetch just the # _ids of objects that match our criteria # 2. Choose a random sample of those _ids # 3. Do an ORM query to fetch the objects with those _ids # 4. Shuffle the results from ming.orm import mapper m = mapper(M.Project) collection = M.main_doc_session.db[m.collection.m.collection_name] docs = list(collection.find(q, {'_id': 1})) if docs: ids = [doc['_id'] for doc in random.sample(docs, min(limit, len(docs)))] if '_id' in q: ids = list(set(q['_id']['$in']).intersection(ids)) q['_id'] = {'$in': ids} projects = M.Project.query.find(q).all() random.shuffle(projects) else: projects = M.Project.query.find(q).limit(limit).sort(sort_key, sort_dir).all() pl = ProjectList() g.resource_manager.register(pl) response = pl.display(projects=projects, display_mode=display_mode, columns=columns, show_proj_icon=show_proj_icon, show_download_button=show_download_button, show_awards_banner=show_awards_banner, grid_view_tools=grid_view_tools) if show_total: if total is None: total = 0 for p in M.Project.query.find(q): if h.has_access(p, 'read')(): total = total + 1 response = '<p class="macro_projects_total">%s Projects</p>%s' % \ (total, response) return response
def get_projects_for_macro(category=None, sort='last_updated', show_total=False, limit=100, labels='', award='', private=False, columns=1, show_proj_icon=True, show_download_button=False, show_awards_banner=True, initial_q={}): from allura.lib.widgets.project_list import ProjectList from allura.lib import utils from allura import model as M # 'trove' is internal substitution for 'category' filter in wiki macro trove = category limit = int(limit) q = dict(deleted=False, is_nbhd_project=False) q.update(initial_q) if labels: or_labels = labels.split('|') q['$or'] = [{'labels': {'$all': l.split(',')}} for l in or_labels] if trove is not None: trove = M.TroveCategory.query.get(fullpath=trove) if award: aw = M.Award.query.find( dict(created_by_neighborhood_id=c.project.neighborhood_id, short=award)).first() if aw: ids = [ grant.granted_to_project_id for grant in M.AwardGrant.query.find( dict(granted_by_neighborhood_id=c.project.neighborhood_id, award_id=aw._id)) ] if '_id' in q: ids = list(set(q['_id']['$in']).intersection(ids)) q['_id'] = {'$in': ids} if trove is not None: q['trove_' + trove.type] = trove._id sort_key, sort_dir = 'last_updated', pymongo.DESCENDING if sort == 'alpha': sort_key, sort_dir = 'name', pymongo.ASCENDING elif sort == 'random': sort_key, sort_dir = None, None elif sort == 'last_registered': sort_key, sort_dir = '_id', pymongo.DESCENDING elif sort == '_id': sort_key, sort_dir = '_id', pymongo.DESCENDING projects = [] if private: # Only return private projects. # Can't filter these with a mongo query directly - have to iterate # through and check the ACL of each project. for chunk in utils.chunked_find(M.Project, q, sort_key=sort_key, sort_dir=sort_dir): projects.extend([p for p in chunk if p.private]) total = len(projects) if sort == 'random': projects = random.sample(projects, min(limit, total)) else: projects = projects[:limit] else: total = None if sort == 'random': # MongoDB doesn't have a random sort built in, so... # 1. Do a direct pymongo query (faster than ORM) to fetch just the # _ids of objects that match our criteria # 2. Choose a random sample of those _ids # 3. Do an ORM query to fetch the objects with those _ids # 4. Shuffle the results from ming.orm import mapper m = mapper(M.Project) collection = M.main_doc_session.db[m.collection.m.collection_name] docs = list(collection.find(q, {'_id': 1})) if docs: ids = [ doc['_id'] for doc in random.sample(docs, min(limit, len(docs))) ] if '_id' in q: ids = list(set(q['_id']['$in']).intersection(ids)) q['_id'] = {'$in': ids} projects = M.Project.query.find(q).all() random.shuffle(projects) else: projects = M.Project.query.find(q).limit(limit).sort( sort_key, sort_dir).all() pl = ProjectList() g.resource_manager.register(pl) response = pl.display( projects=projects, columns=columns, show_proj_icon=show_proj_icon, show_download_button=show_download_button, show_awards_banner=show_awards_banner, ) if show_total: if total is None: total = 0 for p in M.Project.query.find(q): if h.has_access(p, 'read')(): total = total + 1 response = '<p class="macro_projects_total">%s Projects</p>%s' % \ (total, response) return response