Beispiel #1
0
    def get_queryset(self):
        partner = self.request.site.partner
        q = self.request.query_params.get('q')

        if q:
            queryset = Course.search(q)
            queryset = self.get_serializer_class().prefetch_queryset(
                queryset=queryset, partner=partner)
        else:
            if get_query_param(self.request, 'include_hidden_course_runs'):
                course_runs = CourseRun.objects.filter(course__partner=partner)
            else:
                course_runs = CourseRun.objects.filter(
                    course__partner=partner).exclude(hidden=True)

            if get_query_param(self.request, 'marketable_course_runs_only'):
                course_runs = course_runs.marketable().active()

            if get_query_param(
                    self.request,
                    'marketable_enrollable_course_runs_with_archived'):
                course_runs = course_runs.marketable().enrollable()

            if get_query_param(self.request, 'published_course_runs_only'):
                course_runs = course_runs.filter(
                    status=CourseRunStatus.Published)

            queryset = self.get_serializer_class().prefetch_queryset(
                queryset=self.queryset,
                course_runs=course_runs,
                partner=partner)

        return queryset.order_by(Lower('key'))
Beispiel #2
0
    def get_serializer_context(self):
        context = super().get_serializer_context()
        context.update({
            'exclude_utm': get_query_param(self.request, 'exclude_utm'),
            'include_deleted_programs': get_query_param(self.request, 'include_deleted_programs'),
            'include_unpublished_programs': get_query_param(self.request, 'include_unpublished_programs'),
            'include_retired_programs': get_query_param(self.request, 'include_retired_programs'),
        })

        return context
Beispiel #3
0
    def get_queryset(self):
        partner = self.request.site.partner
        q = self.request.query_params.get('q')
        edit_mode = get_query_param(
            self.request,
            'editable') or self.request.method not in SAFE_METHODS

        if edit_mode and q:
            raise EditableAndQUnsupported()

        # Start with either draft versions or real versions of the courses
        if edit_mode:
            # TODO: For now hardcode in draft=True until we choose to roll this out live, DISCO-818
            queryset = Course.objects.filter_drafts(draft=True)
            queryset = CourseEditor.editable_courses(self.request.user,
                                                     queryset)
        else:
            queryset = self.queryset

        if q:
            queryset = Course.search(q, queryset=queryset)
            queryset = self.get_serializer_class().prefetch_queryset(
                queryset=queryset, partner=partner)
        else:
            if edit_mode:
                course_runs = CourseRun.objects.filter_drafts(
                    course__partner=partner)
            else:
                course_runs = CourseRun.objects.filter(course__partner=partner)

            if not get_query_param(self.request, 'include_hidden_course_runs'):
                course_runs = course_runs.exclude(hidden=True)

            if get_query_param(self.request, 'marketable_course_runs_only'):
                course_runs = course_runs.marketable().active()

            if get_query_param(
                    self.request,
                    'marketable_enrollable_course_runs_with_archived'):
                course_runs = course_runs.marketable().enrollable()

            if get_query_param(self.request, 'published_course_runs_only'):
                course_runs = course_runs.filter(
                    status=CourseRunStatus.Published)

            queryset = self.get_serializer_class().prefetch_queryset(
                queryset=queryset, course_runs=course_runs, partner=partner)

        return queryset.order_by(Lower('key'))
Beispiel #4
0
    def get_queryset(self):
        """ List one course run
        ---
        parameters:
            - name: include_deleted_programs
              description: Will include deleted programs in the associated programs array
              required: false
              type: integer
              paramType: query
              multiple: false
        """
        q = self.request.query_params.get('q')
        partner = self.request.site.partner
        edit_mode = get_query_param(self.request, 'editable') or self.request.method not in SAFE_METHODS

        if edit_mode and q:
            raise EditableAndQUnsupported()

        if edit_mode and (not self.request.user.is_staff and not is_publisher_user(self.request.user)):
            raise PermissionDenied

        if edit_mode:
            queryset = CourseRun.objects.filter_drafts()
            queryset = CourseEditor.editable_course_runs(self.request.user, queryset)
        else:
            queryset = self.queryset

        if q:
            qs = SearchQuerySetWrapper(CourseRun.search(q).filter(partner=partner.short_code))
            # This is necessary to avoid issues with the filter backend.
            qs.model = self.queryset.model
            return qs

        queryset = queryset.filter(course__partner=partner)
        return self.get_serializer_class().prefetch_queryset(queryset=queryset)
Beispiel #5
0
    def get_queryset(self):
        """ List one course run
        ---
        parameters:
            - name: include_deleted_programs
              description: Will include deleted programs in the associated programs array
              required: false
              type: integer
              paramType: query
              multiple: false
        """
        q = self.request.query_params.get('q')
        include_all_partners = get_query_param(self.request,
                                               'include_all_partners')
        partners = Partner.objects.all(
        ) if include_all_partners else Partner.objects.filter(
            site=self.request.site)
        edx_org_short_name = self.request.query_params.get('org')

        if q:
            qs = SearchQuerySetWrapper(
                CourseRun.search(q).filter(
                    partner__in=partners.values_list('short_code', flat=True)))
            # This is necessary to avoid issues with the filter backend.
            qs.model = self.queryset.model
            return qs
        else:
            queryset = super(
                CourseRunViewSet,
                self).get_queryset().filter(course__partner__in=partners)
            return self.get_serializer_class().prefetch_queryset(
                queryset=queryset, edx_org_short_name=edx_org_short_name)
Beispiel #6
0
    def get_queryset(self):
        """ List one course run
        ---
        parameters:
            - name: include_deleted_programs
              description: Will include deleted programs in the associated programs array
              required: false
              type: integer
              paramType: query
              multiple: false
        """
        q = self.request.query_params.get('q')
        partner = self.request.site.partner
        edit_mode = get_query_param(self.request, 'editable') or self.request.method not in SAFE_METHODS

        if edit_mode and q:
            raise EditableAndQUnsupported()

        if edit_mode:
            queryset = CourseRun.objects.filter_drafts()
            queryset = CourseEditor.editable_course_runs(self.request.user, queryset)
        else:
            queryset = self.queryset

        if q:
            queryset = CourseRun.search(q, queryset=queryset)

        queryset = queryset.filter(course__partner=partner)
        return self.get_serializer_class().prefetch_queryset(queryset=queryset)
Beispiel #7
0
    def list(self, request, *args, **kwargs):
        """ List all programs.
        ---
        parameters:
            - name: marketable
              description: Retrieve marketable programs. A program is considered marketable if it is active
                and has a marketing slug.
              required: false
              type: integer
              paramType: query
              multiple: false
            - name: published_course_runs_only
              description: Filter course runs by published ones only
              required: false
              type: integer
              paramType: query
              mulitple: false
            - name: marketable_enrollable_course_runs_with_archived
              description: Restrict returned course runs to those that are published, have seats,
                and can be enrolled in now. Includes archived courses.
              required: false
              type: integer
              paramType: query
              mulitple: false
            - name: exclude_utm
              description: Exclude UTM parameters from marketing URLs.
              required: false
              type: integer
              paramType: query
              multiple: false
            - name: use_full_course_serializer
              description: Return all serialized course information instead of a minimal amount of information.
              required: false
              type: integer
              paramType: query
              multiple: false
            - name: types
              description: Filter by comma-separated list of program type slugs
              required: false
              type: string
              paramType: query
              multiple: false
            - name: q
              description: Elasticsearch querystring query. This filter takes precedence over other filters
              required: false
              type: string
              paramType: query
              multiple: false
        """
        if get_query_param(self.request, 'uuids_only'):
            # DRF serializers don't have good support for simple, flat
            # representations like the one we want here.
            queryset = self.filter_queryset(
                Program.objects.filter(partner=self.request.site.partner))
            uuids = queryset.values_list('uuid', flat=True)

            return Response(uuids)

        return super().list(request, *args, **kwargs)
Beispiel #8
0
    def get_serializer_context(self, *args, **kwargs):
        context = super().get_serializer_context(*args, **kwargs)
        query_params = ['exclude_utm', 'include_deleted_programs']

        for query_param in query_params:
            context[query_param] = get_query_param(self.request, query_param)

        return context
Beispiel #9
0
    def get_serializer_context(self, *args, **kwargs):
        context = super().get_serializer_context(*args, **kwargs)
        query_params = ['exclude_utm', 'use_full_course_serializer', 'published_course_runs_only',
                        'marketable_enrollable_course_runs_with_archived']
        for query_param in query_params:
            context[query_param] = get_query_param(self.request, query_param)

        return context
Beispiel #10
0
 def get_serializer_context(self):
     context = super().get_serializer_context()
     query_params = [
         'include_course_runs_staffed',
         'include_publisher_course_runs_staffed'
     ]
     for query_param in query_params:
         context[query_param] = get_query_param(self.request, query_param)
     return context
Beispiel #11
0
    def retrieve(self, request, *args, **kwargs):
        """ Retrieve details for a course. """
        # Check if we can convert from run-level seat pricing to course-level entitlements.
        #
        # Yes, creating an object is kind of an odd thing to do on a GET endpoint - but it's a one time migration
        # to entitlements and subsequent calls will not make further objects.
        # This was deemed simpler than faking that an entitlement exists in the response and making the object when
        # a client calls PATCH.
        course = self.get_object()
        if get_query_param(request, 'editable') and not course.entitlements.exists():
            create_missing_entitlement(course)

        return super(CourseViewSet, self).retrieve(request, *args, **kwargs)
Beispiel #12
0
    def get_queryset(self):
        partner = self.request.site.partner
        q = self.request.query_params.get('q')
        # We don't want to create an additional elasticsearch index right now for draft courses, so we
        # try to implement a basic search behavior with this pubq parameter here against key and name.
        pub_q = self.request.query_params.get('pubq')
        edit_method = self.request.method not in SAFE_METHODS
        edit_mode = get_query_param(self.request, 'editable') or edit_method

        if edit_mode and q:
            raise EditableAndQUnsupported()

        if edit_mode and (not self.request.user.is_staff and not is_publisher_user(self.request.user)):
            raise PermissionDenied

        if edit_mode:
            # Start with either draft versions or real versions of the courses
            queryset = Course.objects.filter_drafts()
            queryset = CourseEditor.editable_courses(self.request.user, queryset, check_editors=edit_method)
        else:
            queryset = self.queryset

        if q:
            queryset = Course.search(q, queryset=queryset)
            queryset = self.get_serializer_class().prefetch_queryset(queryset=queryset, partner=partner)
        else:
            if edit_mode:
                course_runs = CourseRun.objects.filter_drafts(course__partner=partner)
            else:
                course_runs = CourseRun.objects.filter(course__partner=partner)

            if not get_query_param(self.request, 'include_hidden_course_runs'):
                course_runs = course_runs.exclude(hidden=True)

            if get_query_param(self.request, 'marketable_course_runs_only'):
                course_runs = course_runs.marketable().active()

            if get_query_param(self.request, 'marketable_enrollable_course_runs_with_archived'):
                course_runs = course_runs.marketable().enrollable()

            if get_query_param(self.request, 'published_course_runs_only'):
                course_runs = course_runs.filter(status=CourseRunStatus.Published)

            if get_query_param(self.request, 'include_deleted_programs'):
                programs = Program.objects.all()
            else:
                programs = Program.objects.exclude(status=ProgramStatus.Deleted)

            queryset = self.get_serializer_class().prefetch_queryset(
                queryset=queryset,
                course_runs=course_runs,
                partner=partner,
                programs=programs,
            )
        if pub_q and edit_mode:
            return queryset.filter(Q(key__icontains=pub_q) | Q(title__icontains=pub_q)).order_by(Lower('key'))

        return queryset.order_by(Lower('key'))
 def test_without_request(self):
     assert get_query_param(None, 'q') is None
    def test_with_request(self):
        factory = APIRequestFactory()
        request = Request(factory.get('/?q=1'))

        assert get_query_param(request, 'q') == 1
Beispiel #15
0
    def contains(self, request):
        """
        Determine if course runs are found in the query results.

        A dictionary mapping course run keys to booleans,
        indicating course run presence, will be returned.
        ---
        serializer: serializers.ContainedCourseRunsSerializer
        parameters:
            - name: query
              description: Elasticsearch querystring query
              required: true
              type: string
              paramType: query
              multiple: false
            - name: course_run_ids
              description: Comma-separated list of course run IDs
              required: true
              type: string
              paramType: query
              multiple: true
            - name: partner
              description: Filter by partner
              required: false
              type: string
              paramType: query
              multiple: false
            - name: org
              description: Filter results on edx organization's short name.
              required: false
              type: string
              paramType: query
              multiple: false
            - name: include_all_partners
              description: Include courses for all partners.
              required: false
              type: integer
              paramType: query
              multiple: false
        """
        query = request.GET.get('query')
        course_run_ids = request.GET.get('course_run_ids')
        include_all_partners = get_query_param(self.request,
                                               'include_all_partners')
        partners = Partner.objects.all(
        ) if include_all_partners else Partner.objects.filter(
            site=self.request.site)
        edx_org_short_name = request.GET.get('org')

        if query and course_run_ids:
            course_run_ids = course_run_ids.split(',')
            course_runs = CourseRun.search(query).filter(
                partner__in=partners.values_list(
                    'short_code', flat=True)).filter(key__in=course_run_ids)
            # update "course_runs" with edx organization filter
            course_runs = course_runs.filter(
                course__authoring_organizations__key=edx_org_short_name
            ).values_list('key', flat=True)
            contains = {
                course_run_id: course_run_id in course_runs
                for course_run_id in course_run_ids
            }

            instance = {'course_runs': contains}
            serializer = serializers.ContainedCourseRunsSerializer(instance)
            return Response(serializer.data)
        return Response(status=status.HTTP_400_BAD_REQUEST)