Switch to unified view

a/Allura/allura/lib/macro.py b/Allura/allura/lib/macro.py
1
import cgi
1
import cgi
2
import random
2
import shlex
3
import shlex
3
import string
4
import string
4
import logging
5
import logging
5
6
6
import pymongo
7
import pymongo
...
...
135
def projects(category=None, display_mode='grid', sort='last_updated',
136
def projects(category=None, display_mode='grid', sort='last_updated',
136
        show_total=False, limit=100, labels='', award='', private=False):
137
        show_total=False, limit=100, labels='', award='', private=False):
137
    from allura.lib.widgets.project_list import ProjectList
138
    from allura.lib.widgets.project_list import ProjectList
138
    from allura.lib import utils
139
    from allura.lib import utils
139
    from allura import model as M
140
    from allura import model as M
141
    limit = int(limit)
140
    q = dict(
142
    q = dict(
141
        neighborhood_id=c.project.neighborhood_id,
143
        neighborhood_id=c.project.neighborhood_id,
142
        deleted=False,
144
        deleted=False,
143
        shortname={'$ne':'--init--'})
145
        shortname={'$ne':'--init--'})
144
    if labels:
146
    if labels:
...
...
158
    if category is not None:
160
    if category is not None:
159
        q['category_id'] = category._id
161
        q['category_id'] = category._id
160
    sort_key, sort_dir = 'last_updated', pymongo.DESCENDING
162
    sort_key, sort_dir = 'last_updated', pymongo.DESCENDING
161
    if sort == 'alpha':
163
    if sort == 'alpha':
162
        sort_key, sort_dir = 'name', pymongo.ASCENDING
164
        sort_key, sort_dir = 'name', pymongo.ASCENDING
165
    elif sort == 'random':
166
        sort_key, sort_dir = None, None
163
167
168
    projects = []
164
    if private:
169
    if private:
165
        # Only return private projects.
170
        # Only return private projects.
166
        # Can't filter these with a mongo query directly - have to iterate
171
        # Can't filter these with a mongo query directly - have to iterate
167
        # through and check the ACL of each project.
172
        # through and check the ACL of each project.
168
        projects = []
169
        for chunk in utils.chunked_find(M.Project, q, sort_key=sort_key,
173
        for chunk in utils.chunked_find(M.Project, q, sort_key=sort_key,
170
                sort_dir=sort_dir):
174
                sort_dir=sort_dir):
171
            projects.extend([p for p in chunk if p.private])
175
            projects.extend([p for p in chunk if p.private])
172
        total = len(projects)
176
        total = len(projects)
177
        if sort == 'random':
178
            projects = random.sample(projects, min(limit, total))
179
        else:
173
        projects = projects[:int(limit)]
180
            projects = projects[:limit]
174
    else:
181
    else:
175
        total = None
182
        total = None
183
        if sort == 'random':
184
            # MongoDB doesn't have a random sort built in, so...
185
            # 1. Do a direct pymongo query (faster than ORM) to fetch just the
186
            #    _ids of objects that match our criteria
187
            # 2. Choose a random sample of those _ids
188
            # 3. Do an ORM query to fetch the objects with those _ids
189
            # 4. Shuffle the results
190
            from ming.orm import mapper
191
            m = mapper(M.Project)
192
            collection = M.main_doc_session.db[m.collection.m.collection_name]
193
            docs = list(collection.find(q, {'_id': 1}))
194
            if docs:
195
                ids = [doc['_id'] for doc in
196
                        random.sample(docs, min(limit, len(docs)))]
197
                projects = M.Project.query.find(dict(_id={'$in': ids})).all()
198
                random.shuffle(projects)
199
        else:
176
        projects = M.Project.query.find(q).limit(int(limit)).sort(sort_key,
200
            projects = M.Project.query.find(q).limit(limit).sort(sort_key,
177
                sort_dir).all()
201
                sort_dir).all()
178
202
179
    pl = ProjectList()
203
    pl = ProjectList()
180
    g.resource_manager.register(pl)
204
    g.resource_manager.register(pl)
181
    response = pl.display(projects=projects, display_mode=display_mode)
205
    response = pl.display(projects=projects, display_mode=display_mode)