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'))
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
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'))
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)
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)
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)
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)
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
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
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
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)
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
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)