Commit 5f25faf1 by zubair-arbi Committed by Zubair Afzal

add support for course run key in catalog contains endpoint

ENT-201
parent ff0ac78a
...@@ -59,6 +59,20 @@ class CatalogViewSetTests(ElasticsearchTestMixin, SerializationMixin, OAuth2Mixi ...@@ -59,6 +59,20 @@ class CatalogViewSetTests(ElasticsearchTestMixin, SerializationMixin, OAuth2Mixi
self.assertEqual(catalog.query, query) self.assertEqual(catalog.query, query)
self.assertListEqual(list(catalog.viewers), [viewer]) self.assertListEqual(list(catalog.viewers), [viewer])
def assert_catalog_contains_query_string(self, query_string_kwargs, course_key):
"""
Helper method to validate the provided course key or course run key
in the catalog contains endpoint.
"""
query_string = urllib.parse.urlencode(query_string_kwargs)
url = '{base_url}?{query_string}'.format(
base_url=reverse('api:v1:catalog-contains', kwargs={'id': self.catalog.id}),
query_string=query_string
)
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, {'courses': {course_key: True}})
def grant_catalog_permission_to_user(self, user, action, catalog=None): def grant_catalog_permission_to_user(self, user, action, catalog=None):
""" Grant the user access to view `self.catalog`. """ """ Grant the user access to view `self.catalog`. """
catalog = catalog or self.catalog catalog = catalog or self.catalog
...@@ -152,18 +166,24 @@ class CatalogViewSetTests(ElasticsearchTestMixin, SerializationMixin, OAuth2Mixi ...@@ -152,18 +166,24 @@ class CatalogViewSetTests(ElasticsearchTestMixin, SerializationMixin, OAuth2Mixi
assert response.status_code == 200 assert response.status_code == 200
assert response.data['results'] == self.serialize_catalog_course(courses, many=True) assert response.data['results'] == self.serialize_catalog_course(courses, many=True)
def test_contains(self): def test_contains_for_course_key(self):
""" Verify the endpoint returns a filtered list of courses contained in the catalog. """ """
Verify the endpoint returns a filtered list of courses contained in
the catalog for course keys with the format "org+course".
"""
course_key = self.course.key course_key = self.course.key
query_string = urllib.parse.urlencode({'course_id': course_key}) query_string_kwargs = {'course_id': course_key}
url = '{base_url}?{query_string}'.format( self.assert_catalog_contains_query_string(query_string_kwargs, course_key)
base_url=reverse('api:v1:catalog-contains', kwargs={'id': self.catalog.id}),
query_string=query_string def test_contains_for_course_run_key(self):
) """
Verify the endpoint returns a filtered list of courses contained in
response = self.client.get(url) the catalog for course run keys with the format "org/course/run" or
self.assertEqual(response.status_code, 200) "course-v1:org+course+key".
self.assertEqual(response.data, {'courses': {course_key: True}}) """
course_run_key = self.course_run.key
query_string_kwargs = {'course_run_id': course_run_key}
self.assert_catalog_contains_query_string(query_string_kwargs, course_run_key)
def test_csv(self): def test_csv(self):
SeatFactory(type='audit', course_run=self.course_run) SeatFactory(type='audit', course_run=self.course_run)
......
...@@ -113,12 +113,25 @@ class CatalogViewSet(viewsets.ModelViewSet): ...@@ -113,12 +113,25 @@ class CatalogViewSet(viewsets.ModelViewSet):
type: string type: string
paramType: query paramType: query
multiple: true multiple: true
- name: course_run_id
description: Course run IDs to check for existence in the Catalog.
required: false
type: string
paramType: query
multiple: true
""" """
course_ids = request.query_params.get('course_id') course_ids = request.query_params.get('course_id')
course_ids = course_ids.split(',') course_run_ids = request.query_params.get('course_run_id')
catalog = self.get_object() catalog = self.get_object()
courses = catalog.contains(course_ids) courses = {}
if course_ids:
course_ids = course_ids.split(',')
courses.update(catalog.contains(course_ids))
if course_run_ids:
course_run_ids = course_run_ids.split(',')
courses.update(catalog.contains_course_runs(course_run_ids))
instance = {'courses': courses} instance = {'courses': courses}
serializer = serializers.ContainedCoursesSerializer(instance) serializer = serializers.ContainedCoursesSerializer(instance)
......
...@@ -7,7 +7,7 @@ from guardian.shortcuts import get_users_with_perms ...@@ -7,7 +7,7 @@ from guardian.shortcuts import get_users_with_perms
from haystack.query import SearchQuerySet from haystack.query import SearchQuerySet
from course_discovery.apps.core.mixins import ModelPermissionsMixin from course_discovery.apps.core.mixins import ModelPermissionsMixin
from course_discovery.apps.course_metadata.models import Course from course_discovery.apps.course_metadata.models import Course, CourseRun
class Catalog(ModelPermissionsMixin, TimeStampedModel): class Catalog(ModelPermissionsMixin, TimeStampedModel):
...@@ -56,6 +56,23 @@ class Catalog(ModelPermissionsMixin, TimeStampedModel): ...@@ -56,6 +56,23 @@ class Catalog(ModelPermissionsMixin, TimeStampedModel):
return contains return contains
def contains_course_runs(self, course_run_ids): # pylint: disable=unused-argument
"""
Determines if the given course runs are contained in this catalog.
Arguments:
course_run_ids (str[]): List of course run IDs
Returns:
dict: Mapping of course IDs to booleans indicating if course run is
contained in this catalog.
"""
contains = {course_run_id: False for course_run_id in course_run_ids}
course_runs = CourseRun.search(self.query).filter(key__in=course_run_ids).values_list('key', flat=True)
contains.update({course_run_id: course_run_id in course_runs for course_run_id in course_run_ids})
return contains
@property @property
def viewers(self): def viewers(self):
""" Returns a QuerySet of users who have been granted explicit access to view this Catalog. """ Returns a QuerySet of users who have been granted explicit access to view this Catalog.
......
...@@ -5,7 +5,7 @@ from course_discovery.apps.catalogs.models import Catalog ...@@ -5,7 +5,7 @@ from course_discovery.apps.catalogs.models import Catalog
from course_discovery.apps.catalogs.tests import factories from course_discovery.apps.catalogs.tests import factories
from course_discovery.apps.core.tests.factories import UserFactory from course_discovery.apps.core.tests.factories import UserFactory
from course_discovery.apps.core.tests.mixins import ElasticsearchTestMixin from course_discovery.apps.core.tests.mixins import ElasticsearchTestMixin
from course_discovery.apps.course_metadata.tests.factories import CourseFactory from course_discovery.apps.course_metadata.tests.factories import CourseFactory, CourseRunFactory
@ddt.ddt @ddt.ddt
...@@ -39,6 +39,15 @@ class CatalogTests(ElasticsearchTestMixin, TestCase): ...@@ -39,6 +39,15 @@ class CatalogTests(ElasticsearchTestMixin, TestCase):
{self.course.key: True, uncontained_course.key: False} {self.course.key: True, uncontained_course.key: False}
) )
def test_contains_course_runs(self):
""" Verify the method returns a mapping of course run IDs to booleans. """
course_run = CourseRunFactory(course=self.course)
uncontained_course_run = CourseRunFactory(title_override='ABD')
self.assertDictEqual(
self.catalog.contains_course_runs([course_run.key, uncontained_course_run.key]),
{course_run.key: True, uncontained_course_run.key: False}
)
def test_courses_count(self): def test_courses_count(self):
""" Verify the method returns the number of courses contained in the Catalog. """ """ Verify the method returns the number of courses contained in the Catalog. """
self.assertEqual(self.catalog.courses_count, 1) self.assertEqual(self.catalog.courses_count, 1)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment