Commit ddcc5fea by Albert St. Aubin

Added new method to retrieve the course runs for a course based on UUID

This method will retrieve the Course Run information from the Discovery
service based on a Courses UUID.

[LEARNER-3160]
parent 55cc8c61
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('catalog', '0004_auto_20170616_0618'),
]
operations = [
migrations.AddField(
model_name='catalogintegration',
name='long_term_cache_ttl',
field=models.PositiveIntegerField(default=86400, help_text='Specified in seconds (defaults to 86400s, 24hr). In some cases the cache does needs to be refreshed less frequently. Enable long term caching of API responses by setting this to a value greater than 0.', verbose_name='Long Term Cache Time To Live'),
),
]
...@@ -29,6 +29,15 @@ class CatalogIntegration(ConfigurationModel): ...@@ -29,6 +29,15 @@ class CatalogIntegration(ConfigurationModel):
) )
) )
long_term_cache_ttl = models.PositiveIntegerField(
verbose_name=_('Long Term Cache Time To Live'),
default=86400,
help_text=_(
'Specified in seconds (defaults to 86400s, 24hr). In some cases the cache does needs to be refreshed '
'less frequently. Enable long term caching of API responses by setting this to a value greater than 0.'
)
)
service_username = models.CharField( service_username = models.CharField(
max_length=100, max_length=100,
default='lms_catalog_service_user', default='lms_catalog_service_user',
......
...@@ -11,10 +11,11 @@ from student.tests.factories import UserFactory ...@@ -11,10 +11,11 @@ from student.tests.factories import UserFactory
from openedx.core.djangoapps.catalog.cache import PROGRAM_CACHE_KEY_TPL, SITE_PROGRAM_UUIDS_CACHE_KEY_TPL from openedx.core.djangoapps.catalog.cache import PROGRAM_CACHE_KEY_TPL, SITE_PROGRAM_UUIDS_CACHE_KEY_TPL
from openedx.core.djangoapps.catalog.models import CatalogIntegration from openedx.core.djangoapps.catalog.models import CatalogIntegration
from openedx.core.djangoapps.catalog.tests.factories import CourseRunFactory, ProgramFactory, ProgramTypeFactory from openedx.core.djangoapps.catalog.tests.factories import CourseFactory, CourseRunFactory, ProgramFactory, ProgramTypeFactory
from openedx.core.djangoapps.catalog.tests.mixins import CatalogIntegrationMixin from openedx.core.djangoapps.catalog.tests.mixins import CatalogIntegrationMixin
from openedx.core.djangoapps.catalog.utils import ( from openedx.core.djangoapps.catalog.utils import (
get_course_runs, get_course_runs,
get_course_runs_for_course,
get_course_run_details, get_course_run_details,
get_currency_data, get_currency_data,
get_program_types, get_program_types,
...@@ -330,6 +331,18 @@ class TestGetCourseRuns(CatalogIntegrationMixin, TestCase): ...@@ -330,6 +331,18 @@ class TestGetCourseRuns(CatalogIntegrationMixin, TestCase):
self.assert_contract(mock_get_edx_api_data.call_args) self.assert_contract(mock_get_edx_api_data.call_args)
self.assertEqual(data, catalog_course_runs) self.assertEqual(data, catalog_course_runs)
def test_get_course_runs_by_course(self, mock_get_edx_api_data):
"""
Test retrievals of run from a Course.
"""
catalog_course_runs = CourseRunFactory.create_batch(10)
catalog_course = CourseFactory(course_runs=catalog_course_runs)
mock_get_edx_api_data.return_value = catalog_course
data = get_course_runs_for_course(course_uuid=str(catalog_course['uuid']))
self.assertTrue(mock_get_edx_api_data.called)
self.assertEqual(data, catalog_course_runs)
@skip_unless_lms @skip_unless_lms
@mock.patch(UTILS_MODULE + '.get_edx_api_data') @mock.patch(UTILS_MODULE + '.get_edx_api_data')
......
...@@ -210,6 +210,38 @@ def get_course_runs(): ...@@ -210,6 +210,38 @@ def get_course_runs():
return course_runs return course_runs
def get_course_runs_for_course(course_uuid):
catalog_integration = CatalogIntegration.current()
if catalog_integration.is_enabled():
try:
user = catalog_integration.get_service_user()
except ObjectDoesNotExist:
logger.error(
'Catalog service user with username [%s] does not exist. Course runs will not be retrieved.',
catalog_integration.service_username,
)
return []
api = create_catalog_api_client(user)
cache_key = '{base}.course.{uuid}.course_runs'.format(
base=catalog_integration.CACHE_KEY,
uuid=course_uuid
)
data = get_edx_api_data(
catalog_integration,
'courses',
resource_id=course_uuid,
api=api,
cache_key=cache_key if catalog_integration.is_cache_enabled else None,
long_term_cache=True
)
return data.get('course_runs', [])
else:
return []
def get_course_run_details(course_run_key, fields): def get_course_run_details(course_run_key, fields):
""" """
Retrieve information about the course run with the given id Retrieve information about the course run with the given id
......
...@@ -24,7 +24,7 @@ def get_fields(fields, response): ...@@ -24,7 +24,7 @@ def get_fields(fields, response):
def get_edx_api_data(api_config, resource, api, resource_id=None, querystring=None, cache_key=None, many=True, def get_edx_api_data(api_config, resource, api, resource_id=None, querystring=None, cache_key=None, many=True,
traverse_pagination=True, fields=None): traverse_pagination=True, fields=None, long_term_cache=False):
"""GET data from an edX REST API. """GET data from an edX REST API.
DRY utility for handling caching and pagination. DRY utility for handling caching and pagination.
...@@ -42,6 +42,7 @@ def get_edx_api_data(api_config, resource, api, resource_id=None, querystring=No ...@@ -42,6 +42,7 @@ def get_edx_api_data(api_config, resource, api, resource_id=None, querystring=No
many (bool): Whether the resource requested is a collection of objects, or a single object. many (bool): Whether the resource requested is a collection of objects, or a single object.
If false, an empty dict will be returned in cases of failure rather than the default empty list. If false, an empty dict will be returned in cases of failure rather than the default empty list.
traverse_pagination (bool): Whether to traverse pagination or return paginated response.. traverse_pagination (bool): Whether to traverse pagination or return paginated response..
long_term_cache (bool): Whether to use the long term cache ttl or the standard cache ttl
Returns: Returns:
Data returned by the API. When hitting a list endpoint, extracts "results" (list of dict) Data returned by the API. When hitting a list endpoint, extracts "results" (list of dict)
...@@ -81,7 +82,10 @@ def get_edx_api_data(api_config, resource, api, resource_id=None, querystring=No ...@@ -81,7 +82,10 @@ def get_edx_api_data(api_config, resource, api, resource_id=None, querystring=No
if cache_key: if cache_key:
zdata = zpickle(results) zdata = zpickle(results)
cache.set(cache_key, zdata, api_config.cache_ttl) cache_ttl = api_config.cache_ttl
if long_term_cache:
cache_ttl = api_config.long_term_cache_ttl
cache.set(cache_key, zdata, cache_ttl)
return results return results
......
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