def test_paginated_results(self, page_number, page_size, has_next):
        """ Test the page returned has the expected db objects and acts
        like a proper page object.
        """
        id_range = get_object_range(page_number, page_size)
        db_objects = [build_mock_object(obj_id) for obj_id in id_range]
        self.mock_model.objects.filter = MagicMock(return_value=db_objects)

        page = paginate_search_results(self.mock_model, self.search_results, page_size, page_number)

        self.mock_model.objects.filter.assert_called_with(pk__in=id_range)
        self.assertEquals(db_objects, page.object_list)
        self.assertTrue(page.number, page_number)
        self.assertEquals(page.has_next(), has_next)
    def test_paginated_results(self, page_number, page_size, has_next):
        """ Test the page returned has the expected db objects and acts
        like a proper page object.
        """
        id_range = get_object_range(page_number, page_size)
        db_objects = [build_mock_object(obj_id) for obj_id in id_range]
        self.mock_model.objects.filter = MagicMock(return_value=db_objects)

        page = paginate_search_results(self.mock_model, self.search_results,
                                       page_size, page_number)

        self.mock_model.objects.filter.assert_called_with(pk__in=id_range)
        self.assertEquals(db_objects, page.object_list)
        self.assertTrue(page.number, page_number)
        self.assertEquals(page.has_next(), has_next)
Exemple #3
0
    def get(self, request):
        """GET /api/team/v0/teams/"""
        result_filter = {}

        if 'course_id' in request.QUERY_PARAMS:
            course_id_string = request.QUERY_PARAMS['course_id']
            try:
                course_key = CourseKey.from_string(course_id_string)
                # Ensure the course exists
                course_module = modulestore().get_course(course_key)
                if course_module is None:
                    return Response(status=status.HTTP_404_NOT_FOUND)
                result_filter.update({'course_id': course_key})
            except InvalidKeyError:
                error = build_api_error(
                    ugettext_noop("The supplied course id {course_id} is not valid."),
                    course_id=course_id_string,
                )
                return Response(error, status=status.HTTP_400_BAD_REQUEST)

            if not has_team_api_access(request.user, course_key):
                return Response(status=status.HTTP_403_FORBIDDEN)
        else:
            return Response(
                build_api_error(ugettext_noop("course_id must be provided")),
                status=status.HTTP_400_BAD_REQUEST
            )

        text_search = request.QUERY_PARAMS.get('text_search', None)
        if text_search and request.QUERY_PARAMS.get('order_by', None):
            return Response(
                build_api_error(ugettext_noop("text_search and order_by cannot be provided together")),
                status=status.HTTP_400_BAD_REQUEST
            )

        topic_id = request.QUERY_PARAMS.get('topic_id', None)
        if topic_id is not None:
            if topic_id not in [topic['id'] for topic in course_module.teams_configuration['topics']]:
                error = build_api_error(
                    ugettext_noop('The supplied topic id {topic_id} is not valid'),
                    topic_id=topic_id
                )
                return Response(error, status=status.HTTP_400_BAD_REQUEST)
            result_filter.update({'topic_id': topic_id})
        if text_search and CourseTeamIndexer.search_is_enabled():
            try:
                search_engine = CourseTeamIndexer.engine()
            except ElasticSearchConnectionError:
                return Response(
                    build_api_error(ugettext_noop('Error connecting to elasticsearch')),
                    status=status.HTTP_400_BAD_REQUEST
                )
            result_filter.update({'course_id': course_id_string})

            search_results = search_engine.search(
                query_string=text_search.encode('utf-8'),
                field_dictionary=result_filter,
                size=MAXIMUM_SEARCH_SIZE,
            )

            paginated_results = paginate_search_results(
                CourseTeam,
                search_results,
                self.get_paginate_by(),
                self.get_page()
            )
            serializer = self.get_pagination_serializer(paginated_results)
            tracker.emit('edx.team.searched', {
                "number_of_results": search_results['total'],
                "search_text": text_search,
                "topic_id": topic_id,
                "course_id": course_id_string,
            })
        else:
            queryset = CourseTeam.objects.filter(**result_filter)
            order_by_input = request.QUERY_PARAMS.get('order_by', 'name')
            if order_by_input == 'name':
                # MySQL does case-insensitive order_by.
                queryset = queryset.order_by('name')
            elif order_by_input == 'open_slots':
                queryset = queryset.order_by('team_size', '-last_activity_at')
            elif order_by_input == 'last_activity_at':
                queryset = queryset.order_by('-last_activity_at', 'team_size')
            else:
                return Response({
                    'developer_message': "unsupported order_by value {ordering}".format(ordering=order_by_input),
                    # Translators: 'ordering' is a string describing a way
                    # of ordering a list. For example, {ordering} may be
                    # 'name', indicating that the user wants to sort the
                    # list by lower case name.
                    'user_message': _(u"The ordering {ordering} is not supported").format(ordering=order_by_input),
                }, status=status.HTTP_400_BAD_REQUEST)

            page = self.paginate_queryset(queryset)
            serializer = self.get_pagination_serializer(page)
            serializer.context.update({'sort_order': order_by_input})  # pylint: disable=maybe-no-member

        return Response(serializer.data)  # pylint: disable=maybe-no-member
 def test_invalid_page_number(self, page_num):
     """ Test that a Http404 error is raised with non-integer and out-of-range pages
     """
     with self.assertRaises(Http404):
         paginate_search_results(self.mock_model, self.search_results, self.default_size, page_num)
 def test_invalid_page_number(self, page_num):
     """ Test that a Http404 error is raised with non-integer and out-of-range pages
     """
     with self.assertRaises(Http404):
         paginate_search_results(self.mock_model, self.search_results,
                                 self.default_size, page_num)
Exemple #6
0
    def get(self, request):
        """GET /api/team/v0/teams/"""
        result_filter = {'is_active': True}

        if 'course_id' in request.QUERY_PARAMS:
            course_id_string = request.QUERY_PARAMS['course_id']
            try:
                course_key = CourseKey.from_string(course_id_string)
                # Ensure the course exists
                course_module = modulestore().get_course(course_key)
                if course_module is None:
                    return Response(status=status.HTTP_404_NOT_FOUND)
                result_filter.update({'course_id': course_key})
            except InvalidKeyError:
                error = build_api_error(
                    ugettext_noop(
                        "The supplied course id {course_id} is not valid."),
                    course_id=course_id_string,
                )
                return Response(error, status=status.HTTP_400_BAD_REQUEST)

            if not has_team_api_access(request.user, course_key):
                return Response(status=status.HTTP_403_FORBIDDEN)
        else:
            return Response(build_api_error(
                ugettext_noop("course_id must be provided")),
                            status=status.HTTP_400_BAD_REQUEST)

        if 'text_search' in request.QUERY_PARAMS and 'order_by' in request.QUERY_PARAMS:
            return Response(build_api_error(
                ugettext_noop(
                    "text_search and order_by cannot be provided together")),
                            status=status.HTTP_400_BAD_REQUEST)

        if 'topic_id' in request.QUERY_PARAMS:
            topic_id = request.QUERY_PARAMS['topic_id']
            if topic_id not in [
                    topic['id']
                    for topic in course_module.teams_configuration['topics']
            ]:
                error = build_api_error(ugettext_noop(
                    'The supplied topic id {topic_id} is not valid'),
                                        topic_id=topic_id)
                return Response(error, status=status.HTTP_400_BAD_REQUEST)
            result_filter.update(
                {'topic_id': request.QUERY_PARAMS['topic_id']})
        if 'include_inactive' in request.QUERY_PARAMS and request.QUERY_PARAMS[
                'include_inactive'].lower() == 'true':
            del result_filter['is_active']

        if 'text_search' in request.QUERY_PARAMS and CourseTeamIndexer.search_is_enabled(
        ):
            search_engine = CourseTeamIndexer.engine()
            text_search = request.QUERY_PARAMS['text_search'].encode('utf-8')
            result_filter.update({'course_id': course_id_string})

            search_results = search_engine.search(
                query_string=text_search,
                field_dictionary=result_filter,
                size=MAXIMUM_SEARCH_SIZE,
            )

            paginated_results = paginate_search_results(
                CourseTeam, search_results, self.get_paginate_by(),
                self.get_page())

            serializer = self.get_pagination_serializer(paginated_results)
        else:
            queryset = CourseTeam.objects.filter(**result_filter)
            order_by_input = request.QUERY_PARAMS.get('order_by', 'name')
            if order_by_input == 'name':
                queryset = queryset.extra(select={'lower_name': "lower(name)"})
                queryset = queryset.order_by('lower_name')
            elif order_by_input == 'open_slots':
                queryset = queryset.annotate(team_size=Count('users'))
                queryset = queryset.order_by('team_size', '-last_activity_at')
            elif order_by_input == 'last_activity_at':
                queryset = queryset.annotate(team_size=Count('users'))
                queryset = queryset.order_by('-last_activity_at', 'team_size')
            else:
                return Response(
                    {
                        'developer_message':
                        "unsupported order_by value {ordering}".format(
                            ordering=order_by_input),
                        # Translators: 'ordering' is a string describing a way
                        # of ordering a list. For example, {ordering} may be
                        # 'name', indicating that the user wants to sort the
                        # list by lower case name.
                        'user_message':
                        _(u"The ordering {ordering} is not supported").format(
                            ordering=order_by_input),
                    },
                    status=status.HTTP_400_BAD_REQUEST)

            page = self.paginate_queryset(queryset)
            serializer = self.get_pagination_serializer(page)
            serializer.context.update({'sort_order': order_by_input})  # pylint: disable=maybe-no-member

        return Response(serializer.data)  # pylint: disable=maybe-no-member