|
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)
|