def get(self, request, course_key):
        """
        Returns a gradebook entry/entries (i.e. both course and subsection-level grade data)
        for all users enrolled in a course, or a single user enrolled in a course
        if a `username` parameter is provided.

        Args:
            request: A Django request object.
            course_key: The edx course opaque key of a course object.
        """
        course = get_course_by_id(course_key, depth=None)

        # We fetch the entire course structure up-front, and use this when iterating
        # over users to determine their subsection grades.  We purposely avoid fetching
        # the user-specific course structure for each user, because that is very expensive.
        course_data = CourseData(user=None, course=course)
        graded_subsections = list(grades_context.graded_subsections_for_course(course_data.collected_structure))

        if request.GET.get('username'):
            with self._get_user_or_raise(request, course_key) as grade_user:
                course_grade = CourseGradeFactory().read(grade_user, course)

            entry = self._gradebook_entry(grade_user, course, graded_subsections, course_grade)
            serializer = StudentGradebookEntrySerializer(entry)
            return Response(serializer.data)
        else:
            q_objects = []
            if request.GET.get('user_contains'):
                search_term = request.GET.get('user_contains')
                q_objects.append(
                    Q(user__username__icontains=search_term) |
                    Q(programcourseenrollment__program_enrollment__external_user_key__icontains=search_term) |
                    Q(user__email__icontains=search_term)
                )
            if request.GET.get('username_contains'):
                q_objects.append(Q(user__username__icontains=request.GET.get('username_contains')))
            if request.GET.get('cohort_id'):
                cohort = cohorts.get_cohort_by_id(course_key, request.GET.get('cohort_id'))
                if cohort:
                    q_objects.append(Q(user__in=cohort.users.all()))
                else:
                    q_objects.append(Q(user__in=[]))
            if request.GET.get('enrollment_mode'):
                q_objects.append(Q(mode=request.GET.get('enrollment_mode')))

            entries = []
            related_models = ['user']
            users = self._paginate_users(course_key, q_objects, related_models)

            with bulk_gradebook_view_context(course_key, users):
                for user, course_grade, exc in CourseGradeFactory().iter(
                    users, course_key=course_key, collected_block_structure=course_data.collected_structure
                ):
                    if not exc:
                        entry = self._gradebook_entry(user, course, graded_subsections, course_grade)
                        entries.append(entry)

            serializer = StudentGradebookEntrySerializer(entries, many=True)
            return self.get_paginated_response(serializer.data)
Exemple #2
0
    def get(self, request, course_key):
        """
        Returns a gradebook entry/entries (i.e. both course and subsection-level grade data)
        for all users enrolled in a course, or a single user enrolled in a course
        if a `username` parameter is provided.

        Args:
            request: A Django request object.
            course_key: The edx course opaque key of a course object.
        """
        course = get_course_by_id(course_key, depth=None)

        # We fetch the entire course structure up-front, and use this when iterating
        # over users to determine their subsection grades.  We purposely avoid fetching
        # the user-specific course structure for each user, because that is very expensive.
        course_data = CourseData(user=None, course=course)
        graded_subsections = list(grades_context.graded_subsections_for_course(course_data.collected_structure))

        if request.GET.get('username'):
            with self._get_user_or_raise(request, course_key) as grade_user:
                course_grade = CourseGradeFactory().read(grade_user, course)

            entry = self._gradebook_entry(grade_user, course, graded_subsections, course_grade)
            serializer = StudentGradebookEntrySerializer(entry)
            return Response(serializer.data)
        else:
            filter_kwargs = {}
            related_models = []
            if request.GET.get('username_contains'):
                filter_kwargs['user__username__icontains'] = request.GET.get('username_contains')
                related_models.append('user')
            if request.GET.get('cohort_id'):
                cohort = cohorts.get_cohort_by_id(course_key, request.GET.get('cohort_id'))
                if cohort:
                    filter_kwargs['user__in'] = cohort.users.all()
                else:
                    filter_kwargs['user__in'] = []
            if request.GET.get('enrollment_mode'):
                filter_kwargs['mode'] = request.GET.get('enrollment_mode')

            entries = []
            users = self._paginate_users(course_key, filter_kwargs, related_models)

            with bulk_gradebook_view_context(course_key, users):
                for user, course_grade, exc in CourseGradeFactory().iter(
                    users, course_key=course_key, collected_block_structure=course_data.collected_structure
                ):
                    if not exc:
                        entries.append(self._gradebook_entry(user, course, graded_subsections, course_grade))

            serializer = StudentGradebookEntrySerializer(entries, many=True)
            return self.get_paginated_response(serializer.data)
    def get(self, request, course_key):
        """
        Returns a gradebook entry/entries (i.e. both course and subsection-level grade data)
        for all users enrolled in a course, or a single user enrolled in a course
        if a `username` parameter is provided.

        Args:
            request: A Django request object.
            course_key: The edx course opaque key of a course object.
        """
        course = get_course_by_id(course_key, depth=None)

        # We fetch the entire course structure up-front, and use this when iterating
        # over users to determine their subsection grades.  We purposely avoid fetching
        # the user-specific course structure for each user, because that is very expensive.
        course_data = CourseData(user=None, course=course)
        graded_subsections = list(
            grades_context.graded_subsections_for_course(
                course_data.collected_structure))

        if request.GET.get('username'):
            with self._get_user_or_raise(request, course_key) as grade_user:
                course_grade = CourseGradeFactory().read(
                    grade_user,
                    course,
                    collected_block_structure=course_data.collected_structure)
            entry = self._gradebook_entry(grade_user, course,
                                          graded_subsections, course_grade)
            serializer = StudentGradebookEntrySerializer(entry)
            return Response(serializer.data)
        else:
            q_objects = []
            annotations = {}
            if request.GET.get('user_contains'):
                search_term = request.GET.get('user_contains')
                q_objects.append(
                    Q(user__username__icontains=search_term) |
                    Q(programcourseenrollment__program_enrollment__external_user_key__icontains
                      =search_term) | Q(user__email__icontains=search_term))
            if request.GET.get('username_contains'):
                q_objects.append(
                    Q(user__username__icontains=request.GET.get(
                        'username_contains')))
            if request.GET.get('cohort_id'):
                cohort = cohorts.get_cohort_by_id(course_key,
                                                  request.GET.get('cohort_id'))
                if cohort:
                    q_objects.append(Q(user__in=cohort.users.all()))
                else:
                    q_objects.append(Q(user__in=[]))
            if request.GET.get('enrollment_mode'):
                q_objects.append(Q(mode=request.GET.get('enrollment_mode')))
            if request.GET.get('assignment') and (
                    request.GET.get('assignment_grade_max')
                    or request.GET.get('assignment_grade_min')):
                subqueryset = PersistentSubsectionGrade.objects.annotate(
                    effective_grade_percentage=Case(
                        When(override__isnull=False,
                             then=(F('override__earned_graded_override') /
                                   F('override__possible_graded_override')) *
                             100),
                        default=(F('earned_graded') / F('possible_graded')) *
                        100))
                grade_conditions = {
                    'effective_grade_percentage__range':
                    (request.GET.get('assignment_grade_min', 0),
                     request.GET.get('assignment_grade_max', 100))
                }
                annotations['selected_assignment_grade_in_range'] = Exists(
                    subqueryset.filter(course_id=OuterRef('course'),
                                       user_id=OuterRef('user'),
                                       usage_key=UsageKey.from_string(
                                           request.GET.get('assignment')),
                                       **grade_conditions))
                q_objects.append(Q(selected_assignment_grade_in_range=True))
            if request.GET.get('course_grade_min') or request.GET.get(
                    'course_grade_max'):
                grade_conditions = {}
                q_object = Q()
                course_grade_min = request.GET.get('course_grade_min')
                if course_grade_min:
                    course_grade_min = float(
                        request.GET.get('course_grade_min')) / 100
                    grade_conditions['percent_grade__gte'] = course_grade_min

                if request.GET.get('course_grade_max'):
                    course_grade_max = float(
                        request.GET.get('course_grade_max')) / 100
                    grade_conditions['percent_grade__lte'] = course_grade_max

                if not course_grade_min or course_grade_min == 0:
                    subquery_grade_absent = ~Exists(
                        PersistentCourseGrade.objects.filter(
                            course_id=OuterRef('course'),
                            user_id=OuterRef('user_id'),
                        ))

                    annotations['course_grade_absent'] = subquery_grade_absent
                    q_object |= Q(course_grade_absent=True)

                subquery_grade_in_range = Exists(
                    PersistentCourseGrade.objects.filter(
                        course_id=OuterRef('course'),
                        user_id=OuterRef('user_id'),
                        **grade_conditions))
                annotations['course_grade_in_range'] = subquery_grade_in_range
                q_object |= Q(course_grade_in_range=True)

                q_objects.append(q_object)

            entries = []
            related_models = ['user']
            users = self._paginate_users(course_key,
                                         q_objects,
                                         related_models,
                                         annotations=annotations)

            users_counts = self._get_users_counts(course_key,
                                                  q_objects,
                                                  annotations=annotations)

            with bulk_gradebook_view_context(course_key, users):
                for user, course_grade, exc in CourseGradeFactory().iter(
                        users,
                        course_key=course_key,
                        collected_block_structure=course_data.
                        collected_structure):
                    if not exc:
                        entry = self._gradebook_entry(user, course,
                                                      graded_subsections,
                                                      course_grade)
                        entries.append(entry)

            serializer = StudentGradebookEntrySerializer(entries, many=True)
            return self.get_paginated_response(serializer.data, **users_counts)