def list(self, request, *args, **kwargs): if (not settings.RECOMMENDATIONS_ENABLED or not settings.RECOMMENDATIONS_API_URL or not self.request.user.is_authenticated()): return self._popular() else: app_ids = [] url = '{base_url}/api/v2/recommend/{limit}/{user_hash}/'.format( base_url=settings.RECOMMENDATIONS_API_URL, limit=20, user_hash=self.request.user.recommendation_hash) try: with statsd.timer('recommendation.get'): resp = requests.get( url, timeout=settings.RECOMMENDATIONS_API_TIMEOUT) if resp.status_code == 200: app_ids = resp.json()['recommendations'] except Timeout as e: log.warning(u'Recommendation timeout: {error}'.format(error=e)) except RequestException as e: # On recommendation API exceptions we return popular. log.error(u'Recommendation exception: {error}'.format(error=e)) if not app_ids: # Fall back to a popularity search. return self._popular() sq = WebappIndexer.get_app_filter(self.request, app_ids=app_ids) return Response( self.serializer_class(sq.execute().hits, many=True, context={ 'request': self.request }).data)
def list(self, request, *args, **kwargs): if (not settings.RECOMMENDATIONS_ENABLED or not settings.RECOMMENDATIONS_API_URL or not self.request.user.is_authenticated()): return self._popular() else: app_ids = [] url = '{base_url}/api/v2/recommend/{limit}/{user_hash}/'.format( base_url=settings.RECOMMENDATIONS_API_URL, limit=20, user_hash=self.request.user.recommendation_hash) try: with statsd.timer('recommendation.get'): resp = requests.get( url, timeout=settings.RECOMMENDATIONS_API_TIMEOUT) if resp.status_code == 200: app_ids = resp.json()['recommendations'] except Timeout as e: log.warning(u'Recommendation timeout: {error}'.format(error=e)) except RequestException as e: # On recommendation API exceptions we return popular. log.error(u'Recommendation exception: {error}'.format(error=e)) if not app_ids: # Fall back to a popularity search. return self._popular() sq = WebappIndexer.get_app_filter(self.request, app_ids=app_ids) return Response({ 'objects': self.serializer_class( sq.execute().hits, many=True, context={'request': self.request}).data})
def field_to_native_es(self, obj, request): """ A version of field_to_native that uses ElasticSearch to fetch the apps belonging to the collection instead of SQL. Relies on a FeaturedSearchView instance in self.context['view'] to properly rehydrate results returned by ES. """ device = self._get_device(request) app_filters = {'profile': get_feature_profile(request)} if device and device != amo.DEVICE_DESKTOP: app_filters['device'] = device.id qs = WebappIndexer.get_app_filter(request, app_filters) qs = qs.filter('term', **{'collection.id': obj.pk}) qs = qs.sort({ 'collection.order': { 'order': 'asc', 'nested_filter': { 'term': { 'collection.id': obj.pk } } } }) return self.to_native(qs, use_es=True)
def field_to_native_es(self, obj, request): """ A version of field_to_native that uses ElasticSearch to fetch the apps belonging to the collection instead of SQL. Relies on a FeaturedSearchView instance in self.context['view'] to properly rehydrate results returned by ES. """ device = self._get_device(request) app_filters = {'profile': get_feature_profile(request)} if device and device != amo.DEVICE_DESKTOP: app_filters['device'] = device.id qs = WebappIndexer.get_app_filter(request, app_filters) qs = qs.filter('term', **{'collection.id': obj.pk}) qs = qs.sort({ 'collection.order': { 'order': 'asc', 'nested_filter': { 'term': {'collection.id': obj.pk} } } }) return self.to_native(qs, use_es=True)
def test_app_ids(self): """ Test all apps are returned if app IDs is passed. Natural ES limit is 10. """ sq = WebappIndexer.get_app_filter(self.request, app_ids=self.app_ids) results = sq.execute().hits eq_(len(results), 11)
def test_no_filter(self): # Set a couple apps as non-public, the count should decrease. self.apps[0].update(status=amo.STATUS_REJECTED) self.apps[1].update(status=amo.STATUS_PENDING) self.refresh('webapp') sq = WebappIndexer.get_app_filter(self.request, app_ids=self.app_ids) results = sq.execute().hits eq_(len(results), 9)
def test_app_ids(self): """ Test all apps are returned if app IDs is passed. Natural ES limit is 10. """ sq = WebappIndexer.get_app_filter(self.request, app_ids=self.app_ids) results = sq.execute().hits eq_(len(results), 11)
def test_no_filter(self): # Set a couple apps as non-public, the count should decrease. self.apps[0].update(status=amo.STATUS_REJECTED) self.apps[1].update(status=amo.STATUS_PENDING) self.refresh('webapp') sq = WebappIndexer.get_app_filter(self.request, app_ids=self.app_ids) results = sq.execute().hits eq_(len(results), 9)
def _filter(self, req, filters, **kwargs): form = self.form_class(filters) if form.is_valid(): form_data = form.cleaned_data sq = WebappIndexer.get_app_filter( self.req, search_form_to_es_fields(form_data)) return _sort_search(self.req, sq, form_data).to_dict() else: return form.errors.copy()
def test_app_ids(self): """ Test all apps are returned if app IDs is passed. Natural ES limit is 10. """ app_ids = [amo.tests.app_factory().id for i in range(11)] self.refresh('webapp') sq = WebappIndexer.get_app_filter(amo.tests.req_factory_factory(), app_ids=app_ids) results = sq.execute().hits eq_(len(results), 11)
def test_app_ids(self): """ Test all apps are returned if app IDs is passed. Natural ES limit is 10. """ app_ids = [amo.tests.app_factory().id for i in range(11)] self.refresh('webapp') sq = WebappIndexer.get_app_filter(amo.tests.req_factory_factory(), app_ids=app_ids) results = sq.execute().hits eq_(len(results), 11)
def list(self, request, *args, **kwargs): if (not settings.RECOMMENDATIONS_ENABLED or not settings.RECOMMENDATIONS_API_URL or not self.request.user.is_authenticated()): return self._popular() else: app_ids = [] url = '{base_url}/api/v2/recommend/{limit}/{user_hash}/'.format( base_url=settings.RECOMMENDATIONS_API_URL, limit=20, user_hash=self.request.user.recommendation_hash) try: with statsd.timer('recommendation.get'): resp = requests.get( url, timeout=settings.RECOMMENDATIONS_API_TIMEOUT) if resp.status_code == 200: app_ids = resp.json()['recommendations'] except Timeout as e: log.warning(u'Recommendation timeout: {error}'.format(error=e)) except RequestException as e: # On recommendation API exceptions we return popular. log.error(u'Recommendation exception: {error}'.format(error=e)) if not app_ids: # Fall back to a popularity search. return self._popular() # Get list of installed apps and remove from app_ids. installed = list( request.user.installed_set.values_list('addon_id', flat=True)) app_ids = filter(lambda a: a not in installed, app_ids) device = get_device_id(request) filters = {'device': device} if device else None sq = WebappIndexer.get_app_filter(self.request, filters, app_ids=app_ids) return Response({ 'objects': self.serializer_class(sq.execute().hits, many=True, context={ 'request': self.request }).data })
def test_additional_info(self): """ One of the ways `additional_info` is used it to pass the device type of the request and filter apps by device. """ # By default app_factory creates apps with device being # DEVICE_TYPES.keys()[0]. Let's change a couple and query by that # device. device = DEVICE_TYPES.keys()[1] self.apps[0].addondevicetype_set.create(device_type=device) self.apps[1].addondevicetype_set.create(device_type=device) # Reindex b/c we changed an off-model attribute. self.reindex(Webapp, 'webapp') sq = WebappIndexer.get_app_filter(self.request, {'device': device}, app_ids=self.app_ids) results = sq.execute().hits eq_(len(results), 2)
def _filter(self, req, filters, **kwargs): form = self.form_class(filters) if form.is_valid(): form_data = form.cleaned_data sq = WebappIndexer.get_app_filter(self.req, { 'app_type': form_data['app_type'], 'category': form_data['cat'], 'device': form_data['device'], 'is_offline': form_data['offline'], 'manifest_url': form_data['manifest_url'], 'q': form_data['q'], 'premium_type': form_data['premium_types'], 'supported_locales': form_data['languages'], 'tags': form_data['tag'], }) return _sort_search(self.req, sq, form_data).to_dict() else: return form.errors.copy()
def test_additional_info(self): """ One of the ways `additional_info` is used it to pass the device type of the request and filter apps by device. """ # By default app_factory creates apps with device being # DEVICE_TYPES.keys()[0]. Let's change a couple and query by that # device. device = DEVICE_TYPES.keys()[1] self.apps[0].addondevicetype_set.create(device_type=device) self.apps[1].addondevicetype_set.create(device_type=device) # Reindex b/c we changed an off-model attribute. self.reindex(Webapp, 'webapp') sq = WebappIndexer.get_app_filter(self.request, {'device': device}, app_ids=self.app_ids) results = sq.execute().hits eq_(len(results), 2)
def _filter(self, req, filters, **kwargs): form = self.form_class(filters) if form.is_valid(): form_data = form.cleaned_data sq = WebappIndexer.get_app_filter(self.req, { 'app_type': form_data['app_type'], 'author.raw': form_data['author'], 'category': form_data['cat'], 'device': form_data['device'], 'is_offline': form_data['offline'], 'manifest_url': form_data['manifest_url'], 'q': form_data['q'], 'premium_type': form_data['premium_types'], 'supported_locales': form_data['languages'], 'tags': form_data['tag'], }) return _sort_search(self.req, sq, form_data).to_dict() else: return form.errors.copy()
def get_apps(self, request, app_ids): """ Takes a list of app_ids. Gets the apps, including filters. Returns an app_map for serializer context. """ if request.QUERY_PARAMS.get('filtering', '1') == '0': # Without filtering. sq = WebappIndexer.search().filter(es_filter.Bool( should=[es_filter.Terms(id=app_ids)] ))[0:len(app_ids)] else: # With filtering. sq = WebappIndexer.get_app_filter(request, { 'device': self._get_device(request) }, app_ids=app_ids) # Store the apps to attach to feed elements later. apps = sq.execute().hits return dict((app.id, app) for app in apps)
def search(self, request): # Parse form. form = self.form_class(request.GET if request else None) if not form.is_valid(): raise form_errors(form) form_data = form.cleaned_data # Status filter. data = search_form_to_es_fields(form_data) if form_data.get('status') != 'any': data.update(status=form_data.get('status')) # Do filter. sq = apply_reviewer_filters(request, WebappIndexer.search(), data=form_data) sq = WebappIndexer.get_app_filter(request, data, sq=sq, no_filter=True) page = self.paginate_queryset(sq) return self.get_pagination_serializer(page), request.GET.get('q', '')
def search(self, request): # Parse form. form = self.form_class(request.GET if request else None) if not form.is_valid(): raise form_errors(form) form_data = form.cleaned_data # Status filter. data = search_form_to_es_fields(form_data) if form_data.get('status') != 'any': data.update(status=form_data.get('status')) # Do filter. sq = apply_reviewer_filters(request, WebappIndexer.search(), data=form_data) sq = WebappIndexer.get_app_filter(request, data, sq=sq, no_filter=True) page = self.paginate_queryset(sq) return self.get_pagination_serializer(page), request.GET.get('q', '')
def get_apps(self, request, app_ids): """ Takes a list of app_ids. Gets the apps, including filters. Returns an app_map for serializer context. """ if request.QUERY_PARAMS.get('filtering', '1') == '0': # Without filtering. sq = WebappIndexer.search().filter(es_filter.Bool( should=[es_filter.Terms(id=app_ids)] ))[0:len(app_ids)] else: # With filtering. sq = WebappIndexer.get_app_filter(request, { 'device': self._get_device(request) }, app_ids=app_ids) # Store the apps to attach to feed elements later. apps = sq.execute().hits return dict((app.id, app) for app in apps)
def search(self, request): """ Takes a request (expecting request.GET.q), and returns the serializer and search query. """ # Parse form. form = self.form_class(request.GET if request else None) if not form.is_valid(): raise form_errors(form) form_data = form.cleaned_data # Query and filter. sq = WebappIndexer.get_app_filter(request, search_form_to_es_fields(form_data)) # Sort. sq = _sort_search(request, sq, form_data) # Done. page = self.paginate_queryset(sq) return self.get_pagination_serializer(page), form_data.get('q', '')
def search(self, request): """ Takes a request (expecting request.GET.q), and returns the serializer and search query. """ # Parse form. form = self.form_class(request.GET if request else None) if not form.is_valid(): raise form_errors(form) form_data = form.cleaned_data # Query and filter. no_filter = (request.GET.get('filtering', '1') == '0' and acl.action_allowed(request, 'Feed', 'Curate')) sq = WebappIndexer.get_app_filter(request, search_form_to_es_fields(form_data), no_filter=no_filter) # Sort. sq = _sort_search(request, sq, form_data) # Done. page = self.paginate_queryset(sq) return self.get_pagination_serializer(page), form_data.get('q', '')