allura
修訂 | 712680b8a6a082b1dde09996240816d55760048f (tree) |
---|---|
時間 | 2012-04-19 21:12:06 |
作者 | bolkimen <bolkimen@yaho...> |
Commiter | bolkimen |
ticket:40 macro refactored
@@ -134,7 +134,7 @@ def project_blog_posts(max_number=5, sort='timestamp', summary=False, mount_poin | ||
134 | 134 | |
135 | 135 | def get_projects_for_macro(category=None, display_mode='grid', sort='last_updated', |
136 | 136 | show_total=False, limit=100, labels='', award='', private=False, |
137 | - columns=1, show_proj_icon=True, show_download_button=True, macro_type='projects'): | |
137 | + columns=1, show_proj_icon=True, show_download_button=True, initial_q={}): | |
138 | 138 | from allura.lib.widgets.project_list import ProjectList |
139 | 139 | from allura.lib import utils |
140 | 140 | from allura import model as M |
@@ -142,9 +142,10 @@ def get_projects_for_macro(category=None, display_mode='grid', sort='last_update | ||
142 | 142 | trove = category |
143 | 143 | limit = int(limit) |
144 | 144 | q = dict( |
145 | - neighborhood_id=c.project.neighborhood_id, | |
146 | 145 | deleted=False, |
147 | 146 | shortname={'$ne':'--init--'}) |
147 | + q.update(initial_q) | |
148 | + | |
148 | 149 | if labels: |
149 | 150 | or_labels = labels.split('|') |
150 | 151 | q['$or'] = [{'labels': {'$all': l.split(',')}} for l in or_labels] |
@@ -155,10 +156,14 @@ def get_projects_for_macro(category=None, display_mode='grid', sort='last_update | ||
155 | 156 | created_by_neighborhood_id=c.project.neighborhood_id, |
156 | 157 | short=award)).first() |
157 | 158 | if aw: |
158 | - q['_id'] = {'$in': [grant.granted_to_project_id for grant in | |
159 | + ids = [grant.granted_to_project_id for grant in | |
159 | 160 | M.AwardGrant.query.find(dict( |
160 | 161 | granted_by_neighborhood_id=c.project.neighborhood_id, |
161 | - award_id=aw._id))]} | |
162 | + award_id=aw._id))] | |
163 | + if '_id' in q: | |
164 | + ids = list(set(q['_id']['$in']).intersection(ids)) | |
165 | + q['_id'] = {'$in': ids} | |
166 | + | |
162 | 167 | if trove is not None: |
163 | 168 | q['trove_' + trove.type] = trove._id |
164 | 169 | sort_key, sort_dir = 'last_updated', pymongo.DESCENDING |
@@ -171,77 +176,40 @@ def get_projects_for_macro(category=None, display_mode='grid', sort='last_update | ||
171 | 176 | elif sort == '_id': |
172 | 177 | sort_key, sort_dir = '_id', pymongo.DESCENDING |
173 | 178 | |
174 | - if macro_type == 'projects': | |
175 | - projects = [] | |
176 | - if private: | |
177 | - # Only return private projects. | |
178 | - # Can't filter these with a mongo query directly - have to iterate | |
179 | - # through and check the ACL of each project. | |
180 | - for chunk in utils.chunked_find(M.Project, q, sort_key=sort_key, | |
181 | - sort_dir=sort_dir): | |
182 | - projects.extend([p for p in chunk if p.private]) | |
183 | - total = len(projects) | |
184 | - if sort == 'random': | |
185 | - projects = random.sample(projects, min(limit, total)) | |
186 | - else: | |
187 | - projects = projects[:limit] | |
188 | - else: | |
189 | - total = None | |
190 | - if sort == 'random': | |
191 | - # MongoDB doesn't have a random sort built in, so... | |
192 | - # 1. Do a direct pymongo query (faster than ORM) to fetch just the | |
193 | - # _ids of objects that match our criteria | |
194 | - # 2. Choose a random sample of those _ids | |
195 | - # 3. Do an ORM query to fetch the objects with those _ids | |
196 | - # 4. Shuffle the results | |
197 | - from ming.orm import mapper | |
198 | - m = mapper(M.Project) | |
199 | - collection = M.main_doc_session.db[m.collection.m.collection_name] | |
200 | - docs = list(collection.find(q, {'_id': 1})) | |
201 | - if docs: | |
202 | - ids = [doc['_id'] for doc in | |
203 | - random.sample(docs, min(limit, len(docs)))] | |
204 | - if '_id' in q: | |
205 | - ids = list(set(q['_id']['$in']).intersection(ids)) | |
206 | - q['_id'] = {'$in': ids} | |
207 | - projects = M.Project.query.find(q).all() | |
208 | - random.shuffle(projects) | |
209 | - else: | |
210 | - projects = M.Project.query.find(q).limit(limit).sort(sort_key, | |
211 | - sort_dir).all() | |
212 | - | |
213 | - elif macro_type == 'my_projects': | |
214 | - projects = [] | |
215 | - myproj_user = c.user.anonymous() | |
216 | - | |
217 | - if c.project.neighborhood.name == "Users" and c.project.name[:2] == u"u/": | |
218 | - username = c.project.name[2:] | |
219 | - myproj_user = M.User.query.get(username=username) | |
220 | - if 'neighborhood_id' in q: | |
221 | - del q['neighborhood_id'] | |
179 | + projects = [] | |
180 | + if private: | |
181 | + # Only return private projects. | |
182 | + # Can't filter these with a mongo query directly - have to iterate | |
183 | + # through and check the ACL of each project. | |
184 | + for chunk in utils.chunked_find(M.Project, q, sort_key=sort_key, | |
185 | + sort_dir=sort_dir): | |
186 | + projects.extend([p for p in chunk if p.private]) | |
187 | + total = len(projects) | |
188 | + if sort == 'random': | |
189 | + projects = random.sample(projects, min(limit, total)) | |
222 | 190 | else: |
223 | - admin_role_id = M.ProjectRole.query.get(project_id=c.project._id,name='Admin')._id | |
224 | - if c.user is None or c.user == c.user.anonymous(): | |
225 | - project_users_roles = M.ProjectRole.query.find(dict(name=None, project_id=c.project._id)).all() | |
226 | - for ur in project_users_roles: | |
227 | - if admin_role_id in ur.roles: | |
228 | - myproj_user = ur.user | |
229 | - break | |
230 | - else: | |
231 | - myproj_user = c.user | |
232 | - | |
233 | - # Get projects ids | |
234 | - ids = [] | |
235 | - for p in myproj_user.my_projects(): | |
236 | - ids.append(p._id) | |
237 | - if '_id' in q: | |
238 | - ids = list(set(q['_id']['$in']).intersection(ids)) | |
239 | - q['_id'] = {'$in': ids} | |
240 | - | |
191 | + projects = projects[:limit] | |
192 | + else: | |
193 | + total = None | |
241 | 194 | if sort == 'random': |
242 | - ids = random.sample(ids, min(limit, len(ids))) | |
243 | - projects = M.Project.query.find(q).all() | |
244 | - random.shuffle(projects) | |
195 | + # MongoDB doesn't have a random sort built in, so... | |
196 | + # 1. Do a direct pymongo query (faster than ORM) to fetch just the | |
197 | + # _ids of objects that match our criteria | |
198 | + # 2. Choose a random sample of those _ids | |
199 | + # 3. Do an ORM query to fetch the objects with those _ids | |
200 | + # 4. Shuffle the results | |
201 | + from ming.orm import mapper | |
202 | + m = mapper(M.Project) | |
203 | + collection = M.main_doc_session.db[m.collection.m.collection_name] | |
204 | + docs = list(collection.find(q, {'_id': 1})) | |
205 | + if docs: | |
206 | + ids = [doc['_id'] for doc in | |
207 | + random.sample(docs, min(limit, len(docs)))] | |
208 | + if '_id' in q: | |
209 | + ids = list(set(q['_id']['$in']).intersection(ids)) | |
210 | + q['_id'] = {'$in': ids} | |
211 | + projects = M.Project.query.find(q).all() | |
212 | + random.shuffle(projects) | |
245 | 213 | else: |
246 | 214 | projects = M.Project.query.find(q).limit(limit).sort(sort_key, |
247 | 215 | sort_dir).all() |
@@ -266,19 +234,30 @@ def get_projects_for_macro(category=None, display_mode='grid', sort='last_update | ||
266 | 234 | def projects(category=None, display_mode='grid', sort='last_updated', |
267 | 235 | show_total=False, limit=100, labels='', award='', private=False, |
268 | 236 | columns=1, show_proj_icon=True, show_download_button=True): |
237 | + initial_q = dict(neighborhood_id=c.project.neighborhood_id) | |
269 | 238 | return get_projects_for_macro(category=category, display_mode=display_mode, sort=sort, |
270 | 239 | show_total=show_total, limit=limit, labels=labels, award=award, private=private, |
271 | 240 | columns=columns, show_proj_icon=show_proj_icon, show_download_button=show_download_button, |
272 | - macro_type='projects') | |
241 | + initial_q=initial_q) | |
273 | 242 | |
274 | 243 | @macro() |
275 | 244 | def my_projects(category=None, display_mode='grid', sort='last_updated', |
276 | 245 | show_total=False, limit=100, labels='', award='', private=False, |
277 | 246 | columns=1, show_proj_icon=True, show_download_button=True): |
247 | + | |
248 | + myproj_user = c.project.private_project_of() | |
249 | + if myproj_user is None: | |
250 | + myproj_user = c.user.anonymous() | |
251 | + | |
252 | + ids = [] | |
253 | + for p in myproj_user.my_projects(): | |
254 | + ids.append(p._id) | |
255 | + | |
256 | + initial_q = dict(_id={'$in': ids}) | |
278 | 257 | return get_projects_for_macro(category=category, display_mode=display_mode, sort=sort, |
279 | 258 | show_total=show_total, limit=limit, labels=labels, award=award, private=private, |
280 | 259 | columns=columns, show_proj_icon=show_proj_icon, show_download_button=show_download_button, |
281 | - macro_type='my_projects') | |
260 | + initial_q=initial_q) | |
282 | 261 | |
283 | 262 | @macro() |
284 | 263 | def project_screenshots(): |
@@ -228,18 +228,20 @@ def test_projects_macro(): | ||
228 | 228 | |
229 | 229 | @with_setup(setUp) |
230 | 230 | def test_myprojects_macro(): |
231 | - h.set_context('test', 'wiki', neighborhood='Projects') | |
232 | - | |
231 | + h.set_context('u/%s' % (c.user.username), 'wiki', neighborhood='Users') | |
233 | 232 | r = g.markdown_wiki.convert('[[my_projects]]') |
234 | 233 | for p in c.user.my_projects(): |
235 | - if p.neighborhood.name == 'Projects': | |
236 | - proj_title = '<h2><a href="%s">%s</a></h2>' % (p.url(), p.name) | |
237 | - assert proj_title in r | |
234 | + if p.deleted or p.shortname == '--init--': | |
235 | + continue | |
236 | + proj_title = '<h2><a href="%s">%s</a></h2>' % (p.url(), p.name) | |
237 | + assert proj_title in r | |
238 | 238 | |
239 | 239 | h.set_context('u/test-user-1', 'wiki', neighborhood='Users') |
240 | 240 | user = M.User.query.get(username='test-user-1') |
241 | 241 | r = g.markdown_wiki.convert('[[my_projects]]') |
242 | 242 | for p in user.my_projects(): |
243 | + if p.deleted or p.shortname == '--init--': | |
244 | + continue | |
243 | 245 | proj_title = '<h2><a href="%s">%s</a></h2>' % (p.url(), p.name) |
244 | 246 | assert proj_title in r |
245 | 247 |