예제 #1
0
    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)
예제 #2
0
    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})
예제 #3
0
    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)
예제 #4
0
    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)
예제 #5
0
 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)
예제 #6
0
 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)
예제 #7
0
 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)
예제 #8
0
 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)
예제 #9
0
 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()
예제 #10
0
 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)
예제 #11
0
 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)
예제 #12
0
파일: views.py 프로젝트: j-barron/zamboni
    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
            })
예제 #13
0
    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)
예제 #14
0
 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()
예제 #15
0
    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)
예제 #16
0
 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()
예제 #17
0
    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)
예제 #18
0
    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', '')
예제 #19
0
파일: views.py 프로젝트: MaxMillion/zamboni
    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', '')
예제 #20
0
    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)
예제 #21
0
파일: views.py 프로젝트: andymckay/zamboni
    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', '')
예제 #22
0
파일: views.py 프로젝트: j-barron/zamboni
    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', '')