def personas(request, category=None, template=None): categories, filter, base, category = personas_listing(request, category) # Pass the count from base instead of letting it come from # filter.qs.count() since that would join against personas. count = category.count if category else base.count() if "sort" not in request.GET and ((request.MOBILE and not category) or (not request.MOBILE and count > 4)): template += "category_landing.html" else: template += "grid.html" addons = amo.utils.paginate(request, filter.qs, 30, count=count) if category: ids = AddonCategory.creatured_random(category, request.LANG) featured = manual_order(base, ids, pk_name="addons.id") else: ids = Addon.featured_random(request.APP, request.LANG) featured = manual_order(base, ids, pk_name="addons.id") ctx = { "categories": categories, "category": category, "addons": addons, "filter": filter, "sorting": filter.field, "sort_opts": filter.opts, "featured": featured, "search_cat": "personas", "is_homepage": category is None and "sort" not in request.GET, } return jingo.render(request, template, ctx)
def personas(request, category=None, template=None): categories, filter, base, category = personas_listing(request, category) # Pass the count from base instead of letting it come from # filter.qs.count() since that would join against personas. count = category.count if category else base.count() if ('sort' not in request.GET and ((request.MOBILE and not category) or (not request.MOBILE and count > 4))): template += 'category_landing.html' else: template += 'grid.html' addons = amo.utils.paginate(request, filter.qs, 30, count=count) if category: ids = AddonCategory.creatured_random(category, request.LANG) featured = manual_order(base, ids, pk_name="addons.id") else: ids = Addon.featured_random(request.APP, request.LANG) featured = manual_order(base, ids, pk_name="addons.id") ctx = {'categories': categories, 'category': category, 'addons': addons, 'filter': filter, 'sorting': filter.field, 'sort_opts': filter.opts, 'featured': featured, 'search_cat': 'personas', 'is_homepage': category is None and 'sort' not in request.GET} return jingo.render(request, template, ctx)
def personas(request, category=None): categories, filter, base, category = personas_listing(request, category) # Pass the count from base instead of letting it come from # filter.qs.count() since that would join against personas. count = category.count if category else base.count() if 'sort' in request.GET or count < 5: template = 'grid.html' else: template = 'category_landing.html' addons = amo.utils.paginate(request, filter.qs, 30, count=count) if category: ids = AddonCategory.creatured_random(category, request.LANG) featured = manual_order(base, ids, pk_name="addons.id") else: ids = Addon.featured_random(request.APP, request.LANG) featured = manual_order(base, ids, pk_name="addons.id") is_homepage = category is None and 'sort' not in request.GET return jingo.render(request, 'browse/personas/' + template, {'categories': categories, 'category': category, 'filter': filter, 'addons': addons, 'featured': featured, 'is_homepage': is_homepage, 'search_cat': 'personas'})
def personas(request, category=None, template=None): listing = personas_listing(request, category) # I guess this was a Complete Theme after all. if isinstance(listing, (HttpResponsePermanentRedirect, HttpResponseRedirect)): return listing categories, filter_, base, cat = listing if filter_.field == "up-and-coming": # Almost hardcoding the number of element because performing # `filter_.qs.count()` is a performance killer. We're still # verifying the `base.count()` for the template switch below. base_count = base.count() count = ( base_count if base_count < MIN_COUNT_FOR_LANDING else PAGINATE_PERSONAS_BY * settings.PERSONA_DEFAULT_PAGES ) else: # Pass the count from base instead of letting it come from # filter_.qs.count() since that would join against personas. count = cat.count if cat else base.count() addons = amo.utils.paginate(request, filter_.qs, PAGINATE_PERSONAS_BY, count=count) if "sort" not in request.GET and ( (request.MOBILE and not cat) or (not request.MOBILE and count > MIN_COUNT_FOR_LANDING) ): template += "category_landing.html" else: template += "grid.html" if cat: ids = AddonCategory.creatured_random(cat, request.LANG) featured = manual_order(base, ids, pk_name="addons.id") else: ids = Addon.featured_random(request.APP, request.LANG) featured = manual_order(base, ids, pk_name="addons.id") ctx = { "categories": categories, "category": cat, "addons": addons, "filter": filter_, "sorting": filter_.field, "sort_opts": filter_.opts, "featured": featured, "search_cat": "themes", "is_homepage": cat is None and "sort" not in request.GET, } return render(request, template, ctx)
def creatured(request, category): TYPE = amo.ADDON_EXTENSION q = Category.objects.filter(application=request.APP.id, type=TYPE) category = get_object_or_404(q, slug=category) ids = AddonCategory.creatured_random(category, request.LANG) addons = manual_order(Addon.objects.public(), ids, pk_name="addons.id") return render(request, "browse/creatured.html", {"addons": addons, "category": category, "sorting": "featured"})
def process_request(self, list_type='recommended', addon_type='ALL', limit=10, platform='ALL', version=None): """ Find a list of new or featured add-ons. Filtering is done in Python for cache-friendliness and to avoid heavy queries. """ limit = min(MAX_LIMIT, int(limit)) APP, platform = self.request.APP, platform.lower() qs = Addon.objects.listed(APP) shuffle = True if list_type in ('by_adu', 'featured'): qs = qs.exclude(type=amo.ADDON_PERSONA) if list_type == 'newest': new = date.today() - timedelta(days=NEW_DAYS) addons = (qs.filter(created__gte=new) .order_by('-created'))[:limit + BUFFER] elif list_type == 'by_adu': addons = qs.order_by('-average_daily_users')[:limit + BUFFER] shuffle = False # By_adu is an ordered list. elif list_type == 'hotness': # Filter to type=1 so we hit visible_idx. Only extensions have a # hotness index right now so this is not incorrect. addons = (qs.filter(type=amo.ADDON_EXTENSION) .order_by('-hotness'))[:limit + BUFFER] shuffle = False else: ids = Addon.featured_random(APP, self.request.LANG) addons = manual_order(qs, ids[:limit + BUFFER], 'addons.id') shuffle = False args = (addon_type, limit, APP, platform, version, shuffle) f = lambda: self._process(addons, *args) return cached_with(addons, f, map(encoding.smart_str, args))
def _landing(request, category=None): if category: featured = '' category = get_list_or_404( Category.objects.filter(type=amo.ADDON_PERSONA, slug=category))[0] popular = (Addon.objects.public() .filter(type=amo.ADDON_PERSONA, addoncategory__category__id=category.id) .order_by('-persona__popularity')[:12]) categories, filter, base, category = personas_listing(request, category.slug) ids = AddonCategory.creatured_random(category, request.LANG) featured = manual_order(base, ids, pk_name="addons.id")[:12] else: popular = (Addon.objects.public().filter(type=amo.ADDON_PERSONA) .order_by('-persona__popularity')[:12]) featured = get_featured_personas(request, num_personas=12) return jingo.render(request, 'themes/landing.html', { 'category': category, 'popular': popular, 'featured': featured, })
def _do_sort_queue_obj(request, qs, date_sort): """ Column sorting logic based on request GET parameters. Deals with objects with joins on the Addon (e.g. RereviewQueue, Version). Returns qs of apps. """ sort_type, order = clean_sort_param(request, date_sort=date_sort) sort_str = sort_type if sort_type not in [date_sort, 'name']: sort_str = 'addon__' + sort_type # sort_str includes possible joins when ordering. # sort_type is the name of the field to sort on without desc/asc markers. # order_by is the name of the field to sort on with desc/asc markers. order_by = ('-' if order == 'desc' else '') + sort_str # Sort. if sort_type == 'name': # Sorting by name translation through an addon foreign key. return order_by_translation( Webapp.objects.filter(id__in=qs.values_list('addon', flat=True)), order_by) elif sort_type == 'num_abuse_reports': qs = qs.annotate(num_abuse_reports=Count('abuse_reports')) # Convert sorted queue object queryset to sorted app queryset. sorted_app_ids = (qs.order_by('-addon__priority_review', order_by) .values_list('addon', flat=True)) qs = Webapp.objects.filter(id__in=sorted_app_ids) return manual_order(qs, sorted_app_ids, 'addons.id')
def test_ordering(self): """Given a specific set of primary keys, assure that we return addons in that order.""" semi_arbitrary_order = [40, 5299, 3615] addons = manual_order(Addon.objects.all(), semi_arbitrary_order) eq_(semi_arbitrary_order, [addon.id for addon in addons])
def get_result_set(self, term, result, offset, limit): # Return results as a list of add-ons. addon_ids = [m['attrs']['addon_id'] for m in result['matches']] addons = manual_order(Addon.objects.all(), addon_ids) return ResultSet(addons, min(self.total_found, SPHINX_HARD_LIMIT), offset)
def get_result_set(self, term, result, offset, limit): # Return results as a list of add-ons. addon_ids = [m['attrs']['addon_id'] for m in result['matches']] log.debug([(m['attrs']['addon_id'], m['attrs'].get('myweight')) for m in result['matches']]) addons = manual_order(Addon.objects.all(), addon_ids) return ResultSet(addons, min(self.total_found, SPHINX_HARD_LIMIT), offset)
def personas(request, category=None, template=None): listing = personas_listing(request, category) # I guess this was a Complete Theme after all. if isinstance(listing, (HttpResponsePermanentRedirect, HttpResponseRedirect)): return listing categories, filter_, base, cat = listing if filter_.field == 'up-and-coming': # Almost hardcoding the number of element because performing # `filter_.qs.count()` is a performance killer. We're still # verifying the `base.count()` for the template switch below. base_count = base.count() count = (base_count if base_count < MIN_COUNT_FOR_LANDING else PAGINATE_PERSONAS_BY * settings.PERSONA_DEFAULT_PAGES) else: # Pass the count from base instead of letting it come from # filter_.qs.count() since that would join against personas. count = cat.count if cat else base.count() addons = amo.utils.paginate(request, filter_.qs, PAGINATE_PERSONAS_BY, count=count) if ('sort' not in request.GET and ( (request.MOBILE and not cat) or (not request.MOBILE and count > MIN_COUNT_FOR_LANDING))): template += 'category_landing.html' else: template += 'grid.html' if cat: ids = AddonCategory.creatured_random(cat, request.LANG) featured = manual_order(base, ids, pk_name="addons.id") else: ids = Addon.featured_random(request.APP, request.LANG) featured = manual_order(base, ids, pk_name="addons.id") ctx = {'categories': categories, 'category': cat, 'addons': addons, 'filter': filter_, 'sorting': filter_.field, 'sort_opts': filter_.opts, 'featured': featured, 'search_cat': 'themes', 'is_homepage': cat is None and 'sort' not in request.GET} return render(request, template, ctx)
def creatured(request, category): TYPE = amo.ADDON_EXTENSION q = Category.objects.filter(application=request.APP.id, type=TYPE) category = get_object_or_404(q, slug=category) ids = AddonCategory.creatured_random(category, request.LANG) addons = manual_order(Addon.objects.public(), ids, pk_name='addons.id') return render(request, 'browse/creatured.html', {'addons': addons, 'category': category, 'sorting': 'featured'})
def filter(self, field): qs = self.base_queryset if field == 'purchased': # Id's are in created order, so let's invert them for this query. # According to my testing we don't actually need to dedupe this. ids = list(reversed(self.ids[0])) + self.ids[1] return manual_order(qs.filter(id__in=ids), ids) elif field == 'price': return (qs.filter(id__in=self.uids).order_by( 'addonpremium__price__price', 'id')) elif field == 'name': return order_by_translation(qs.filter(id__in=self.uids), 'name')
def filter(self, field): qs = self.base_queryset if field == 'purchased': # Id's are in created order, so let's invert them for this query. # According to my testing we don't actually need to dedupe this. ids = list(reversed(self.ids[0])) + self.ids[1] return manual_order(qs.filter(id__in=ids), ids) elif field == 'price': return (qs.filter(id__in=self.uids) .order_by('addonpremium__price__price', 'id')) elif field == 'name': return order_by_translation(qs.filter(id__in=self.uids), 'name')
def personas(request, category=None, template=None): listing = personas_listing(request, category) # I guess this was a Complete Theme after all. if isinstance(listing, (HttpResponsePermanentRedirect, HttpResponseRedirect)): return listing categories, filter, base, category = listing # Pass the count from base instead of letting it come from # filter.qs.count() since that would join against personas. count = category.count if category else base.count() if ('sort' not in request.GET and ((request.MOBILE and not category) or (not request.MOBILE and count > 4))): template += 'category_landing.html' else: template += 'grid.html' addons = amo.utils.paginate(request, filter.qs, 30, count=count) if category: ids = AddonCategory.creatured_random(category, request.LANG) featured = manual_order(base, ids, pk_name="addons.id") else: ids = Addon.featured_random(request.APP, request.LANG) featured = manual_order(base, ids, pk_name="addons.id") ctx = { 'categories': categories, 'category': category, 'addons': addons, 'filter': filter, 'sorting': filter.field, 'sort_opts': filter.opts, 'featured': featured, 'search_cat': 'themes', 'is_homepage': category is None and 'sort' not in request.GET } return render(request, template, ctx)
def filter_featured(self): # Featured search add-ons in all locales: APP, LANG = self.request.APP, self.request.LANG ids = get_featured_ids(APP, LANG, amo.ADDON_SEARCH) try: search_cat = Category.objects.get(slug="search-tools", application=APP.id) others = get_creatured_ids(search_cat, LANG) ids.extend(o for o in others if o not in ids) except Category.DoesNotExist: pass return manual_order(Addon.objects.valid(), ids, "addons.id")
def _tags_meta(self, results, **kwargs): r = results[self.queries['tag']] tag_dict = defaultdict(int) if 'matches' not in r: return [] for m in r['matches']: for tag_id in m['attrs']['tag']: tag_dict[tag_id] += 1 tag_dict_sorted = sorted(tag_dict.iteritems(), key=lambda x: x[1], reverse=True)[:MAX_TAGS] tag_ids = [k for k, v in tag_dict_sorted] return manual_order(Tag.objects.all(), tag_ids)
def filter_featured(self): # Featured search add-ons in all locales: APP, LANG = self.request.APP, self.request.LANG ids = get_featured_ids(APP, LANG, amo.ADDON_SEARCH) try: search_cat = Category.objects.get(slug='search-tools', application=APP.id) others = get_creatured_ids(search_cat, LANG) ids.extend(o for o in others if o not in ids) except Category.DoesNotExist: pass return manual_order(Addon.objects.valid(), ids, 'addons.id')
def get(self, request, api_version, list_type='recommended', addon_type='ALL', limit=10, platform='ALL', version=None, compat_mode='strict', format=None): """ Find a list of new or featured add-ons. Filtering is done in Python for cache-friendliness and to avoid heavy queries. """ limit = min(MAX_LIMIT, int(limit)) APP, platform = self.request.APP, platform.lower() qs = Addon.objects.listed(APP).exclude(type=amo.ADDON_WEBAPP) shuffle = True if list_type in ('by_adu', 'featured'): qs = qs.exclude(type=amo.ADDON_PERSONA) if list_type == 'newest': new = date.today() - timedelta(days=NEW_DAYS) addons = (qs.filter( created__gte=new).order_by('-created'))[:limit + BUFFER] elif list_type == 'by_adu': addons = qs.order_by('-average_daily_users')[:limit + BUFFER] shuffle = False # By_adu is an ordered list. elif list_type == 'hotness': # Filter to type=1 so we hit visible_idx. Only extensions have a # hotness index right now so this is not incorrect. addons = (qs.filter( type=amo.ADDON_EXTENSION).order_by('-hotness'))[:limit + BUFFER] shuffle = False else: ids = Addon.featured_random(APP, self.request.LANG) addons = manual_order(qs, ids[:limit + BUFFER], 'addons.id') shuffle = False args = (addon_type, limit, APP, platform, version, compat_mode, shuffle) response = self.create_response(addon_filter(addons, *args)) # Storing addons within the response to be able to use it later # in `self.finalize_response()` as a cache key. response.addons = addons return response
def process_request(self, list_type='recommended', addon_type='ALL', limit=10, platform='ALL', version=None, compat_mode='strict'): """ Find a list of new or featured add-ons. Filtering is done in Python for cache-friendliness and to avoid heavy queries. """ limit = min(MAX_LIMIT, int(limit)) APP, platform = self.request.APP, platform.lower() qs = Addon.objects.listed(APP) shuffle = True if list_type in ('by_adu', 'featured'): qs = qs.exclude(type=amo.ADDON_PERSONA) if list_type == 'newest': new = date.today() - timedelta(days=NEW_DAYS) addons = (qs.filter( created__gte=new).order_by('-created'))[:limit + BUFFER] elif list_type == 'by_adu': addons = qs.order_by('-average_daily_users')[:limit + BUFFER] shuffle = False # By_adu is an ordered list. elif list_type == 'hotness': # Filter to type=1 so we hit visible_idx. Only extensions have a # hotness index right now so this is not incorrect. addons = (qs.filter( type=amo.ADDON_EXTENSION).order_by('-hotness'))[:limit + BUFFER] shuffle = False else: ids = Addon.featured_random(APP, self.request.LANG) addons = manual_order(qs, ids[:limit + BUFFER], 'addons.id') shuffle = False args = (addon_type, limit, APP, platform, version, compat_mode, shuffle) def f(): return self._process(addons, *args) return cached_with(addons, f, map(encoding.smart_str, args))
def _queue_to_apps(request, queue_qs): """Apply sorting and filtering to queue queryset and return apps within that queue in sorted order. Args: queue_qs -- queue queryset (e.g. RereviewQueue, EscalationQueue) """ # Preserve the sort order by storing the properly sorted ids. sorted_app_ids = _do_sort(request, queue_qs).values_list("addon", flat=True) # The filter below undoes the sort above. qs, search_form = _get_search_form(request, Webapp.objects.filter(id__in=sorted_app_ids)) # Put the filtered qs back into the correct sort order. qs = manual_order(qs, sorted_app_ids) apps = [QueuedApp(app, app.created) for app in qs] return apps, search_form
def _queue_to_apps(request, queue_qs, date_field="created"): """Apply sorting and filtering to queue queryset and return apps within that queue in sorted order. Args: queue_qs -- queue queryset (e.g. RereviewQueue, EscalationQueue) date_field -- field to sort on """ # Preserve the sort order by storing the properly sorted ids. sorted_app_ids = _do_sort(request, queue_qs, date_field=date_field).values_list("addon", flat=True) # The filter below undoes the sort above. qs = Webapp.objects.filter(id__in=sorted_app_ids) # Put the filtered qs back into the correct sort order. qs = manual_order(qs, sorted_app_ids, "addons.id") return qs
def _queue_to_apps(request, queue_qs, date_field='created'): """Apply sorting and filtering to queue queryset and return apps within that queue in sorted order. Args: queue_qs -- queue queryset (e.g. RereviewQueue, EscalationQueue) date_field -- field to sort on """ # Preserve the sort order by storing the properly sorted ids. sorted_app_ids = (_do_sort(request, queue_qs, date_field=date_field) .values_list('addon', flat=True)) # The filter below undoes the sort above. qs = Webapp.objects.filter(id__in=sorted_app_ids) # Put the filtered qs back into the correct sort order. qs = manual_order(qs, sorted_app_ids, 'addons.id') return qs
def get(self, request, api_version, list_type='recommended', addon_type='ALL', limit=10, platform='ALL', version=None, compat_mode='strict', format=None): """ Find a list of new or featured add-ons. Filtering is done in Python for cache-friendliness and to avoid heavy queries. """ limit = min(MAX_LIMIT, int(limit)) APP, platform = self.request.APP, platform.lower() qs = Addon.objects.listed(APP).exclude(type=amo.ADDON_WEBAPP) shuffle = True if list_type in ('by_adu', 'featured'): qs = qs.exclude(type=amo.ADDON_PERSONA) if list_type == 'newest': new = date.today() - timedelta(days=NEW_DAYS) addons = (qs.filter(created__gte=new) .order_by('-created'))[:limit + BUFFER] elif list_type == 'by_adu': addons = qs.order_by('-average_daily_users')[:limit + BUFFER] shuffle = False # By_adu is an ordered list. elif list_type == 'hotness': # Filter to type=1 so we hit visible_idx. Only extensions have a # hotness index right now so this is not incorrect. addons = (qs.filter(type=amo.ADDON_EXTENSION) .order_by('-hotness'))[:limit + BUFFER] shuffle = False else: ids = Addon.featured_random(APP, self.request.LANG) addons = manual_order(qs, ids[:limit + BUFFER], 'addons.id') shuffle = False args = (addon_type, limit, APP, platform, version, compat_mode, shuffle) response = self.create_response(addon_filter(addons, *args)) # Storing addons within the response to be able to use it later # in `self.finalize_response()` as a cache key. response.addons = addons return response
def _queue_to_apps(request, queue_qs): """Apply sorting and filtering to queue queryset and return apps within that queue in sorted order. Args: queue_qs -- queue queryset (e.g. RereviewQueue, EscalationQueue) """ # Preserve the sort order by storing the properly sorted ids. sorted_app_ids = (_do_sort(request, queue_qs).values_list('addon', flat=True)) # The filter below undoes the sort above. qs, search_form = _get_search_form( request, Webapp.objects.filter(id__in=sorted_app_ids)) # Put the filtered qs back into the correct sort order. qs = manual_order(qs, sorted_app_ids, 'addons.id') [QueuedApp(app, app.created) for app in qs] return qs, search_form
def filter_featured(self): ids = self.model.featured_random(self.request.APP, self.request.LANG) return manual_order(self.base_queryset, ids, 'addons.id')
def order_featured(self, filter): return manual_order(filter, self.featured_ids, 'addon_id')
def featured(request, category=None, template=None): ids = Addon.featured_random(request.APP, request.LANG) addons = manual_order(Addon.objects.exclude(type=amo.ADDON_PERSONA), ids) return jingo.render(request, template, {'addons': addons})
def filter_featured(self): qs = self.base_queryset.all() return manual_order(qs, self.ids, pk_name='addons.id')
def order_featured(self, filter): return manual_order(filter, self.ids, pk_name='addons.id')
def get_featured_personas(request): categories, filter, base, category = personas_listing(request) ids = get_featured_ids(request.APP, request.LANG, type=amo.ADDON_PERSONA) return manual_order(base, ids)[:6]
def get_featured_personas(request, category=None, num_personas=6): categories, filter, base, category = personas_listing(request, category) ids = get_featured_ids(request.APP, request.LANG, type=amo.ADDON_PERSONA) return manual_order(base, ids, 'addons.id')[:num_personas]
def get_featured_personas(request): categories, filter, base, category = personas_listing(request) ids = FeaturedManager.featured_ids(request.APP, request.LANG, type=amo.ADDON_PERSONA) return manual_order(base, ids)[:6]
def filter_featured(self): ids = self.model.featured_random(self.request.APP, self.request.LANG) return manual_order(self.model.objects, ids, 'addons.id')