Update Course About API to include effort and video
MA-1661
This commit is contained in:
@@ -11,6 +11,7 @@ from rest_framework import serializers
|
||||
|
||||
from lms.djangoapps.courseware.courses import get_course_about_section
|
||||
from openedx.core.lib.courses import course_image_url
|
||||
from openedx.core.djangoapps.models.course_details import CourseDetails
|
||||
from xmodule.course_module import DEFAULT_START_DATE
|
||||
|
||||
|
||||
@@ -36,6 +37,10 @@ class _CourseApiMediaCollectionSerializer(serializers.Serializer): # pylint: di
|
||||
Nested serializer to represent a collection of media objects
|
||||
"""
|
||||
course_image = _MediaSerializer(source='*', uri_parser=course_image_url)
|
||||
course_video = _MediaSerializer(
|
||||
source='*',
|
||||
uri_parser=lambda course: CourseDetails.fetch_video_url(course.id),
|
||||
)
|
||||
|
||||
|
||||
class CourseSerializer(serializers.Serializer): # pylint: disable=abstract-method
|
||||
@@ -47,14 +52,19 @@ class CourseSerializer(serializers.Serializer): # pylint: disable=abstract-meth
|
||||
name = serializers.CharField(source='display_name_with_default')
|
||||
number = serializers.CharField(source='display_number_with_default')
|
||||
org = serializers.CharField(source='display_org_with_default')
|
||||
description = serializers.SerializerMethodField()
|
||||
short_description = serializers.SerializerMethodField()
|
||||
effort = serializers.SerializerMethodField()
|
||||
|
||||
media = _CourseApiMediaCollectionSerializer(source='*')
|
||||
|
||||
start = serializers.DateTimeField()
|
||||
start_type = serializers.SerializerMethodField()
|
||||
start_display = serializers.SerializerMethodField()
|
||||
end = serializers.DateTimeField()
|
||||
|
||||
enrollment_start = serializers.DateTimeField()
|
||||
enrollment_end = serializers.DateTimeField()
|
||||
|
||||
blocks_url = serializers.SerializerMethodField()
|
||||
|
||||
def get_start_type(self, course):
|
||||
@@ -79,9 +89,9 @@ class CourseSerializer(serializers.Serializer): # pylint: disable=abstract-meth
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_description(self, course):
|
||||
def get_short_description(self, course):
|
||||
"""
|
||||
Get the representation for SerializerMethodField `description`
|
||||
Get the representation for SerializerMethodField `short_description`
|
||||
"""
|
||||
return get_course_about_section(self.context['request'], course, 'short_description').strip()
|
||||
|
||||
@@ -94,3 +104,9 @@ class CourseSerializer(serializers.Serializer): # pylint: disable=abstract-meth
|
||||
urllib.urlencode({'course_id': course.id}),
|
||||
])
|
||||
return self.context['request'].build_absolute_uri(base_url)
|
||||
|
||||
def get_effort(self, course):
|
||||
"""
|
||||
Get the representation for SerializerMethodField `effort`
|
||||
"""
|
||||
return CourseDetails.fetch_effort(course.id)
|
||||
|
||||
@@ -19,44 +19,18 @@ class CourseApiTestMixin(CourseApiFactoryMixin):
|
||||
"""
|
||||
Establish basic functionality for Course API tests
|
||||
"""
|
||||
|
||||
maxDiff = 5000 # long enough to show mismatched dicts
|
||||
|
||||
expected_course_data = {
|
||||
'course_id': u'edX/toy/2012_Fall',
|
||||
'name': u'Toy Course',
|
||||
'number': u'toy',
|
||||
'org': u'edX',
|
||||
'description': u'A course about toys.',
|
||||
'media': {
|
||||
'course_image': {
|
||||
'uri': u'/c4x/edX/toy/asset/just_a_test.jpg',
|
||||
}
|
||||
},
|
||||
'start': u'2015-07-17T12:00:00Z',
|
||||
'start_type': u'timestamp',
|
||||
'start_display': u'July 17, 2015',
|
||||
'end': u'2015-09-19T18:00:00Z',
|
||||
'enrollment_start': u'2015-06-15T00:00:00Z',
|
||||
'enrollment_end': u'2015-07-15T00:00:00Z',
|
||||
'blocks_url': '/api/courses/v1/blocks/?course_id=edX%2Ftoy%2F2012_Fall',
|
||||
}
|
||||
|
||||
def verify_course(self, course, course_id=None):
|
||||
"""
|
||||
Ensure that the returned course is the course we just created
|
||||
"""
|
||||
|
||||
if course_id is None:
|
||||
course_id = self.expected_course_data['course_id']
|
||||
self.assertIsInstance(course, CourseDescriptor)
|
||||
self.assertEqual(course_id, str(course.id))
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(CourseApiTestMixin, cls).setUpClass()
|
||||
cls.request_factory = APIRequestFactory()
|
||||
|
||||
def verify_course(self, course, course_id=u'edX/toy/2012_Fall'):
|
||||
"""
|
||||
Ensure that the returned course is the course we just created
|
||||
"""
|
||||
self.assertIsInstance(course, CourseDescriptor)
|
||||
self.assertEqual(course_id, str(course.id))
|
||||
|
||||
|
||||
class CourseDetailTestMixin(CourseApiTestMixin):
|
||||
"""
|
||||
|
||||
@@ -4,6 +4,7 @@ Test data created by CourseSerializer
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from openedx.core.djangoapps.models.course_details import CourseDetails
|
||||
from rest_framework.test import APIRequestFactory
|
||||
from rest_framework.request import Request
|
||||
|
||||
@@ -18,6 +19,7 @@ class TestCourseSerializerFields(CourseApiFactoryMixin, ModuleStoreTestCase):
|
||||
"""
|
||||
Test variations of start_date field responses
|
||||
"""
|
||||
maxDiff = 5000 # long enough to show mismatched dicts, in case of error
|
||||
|
||||
def setUp(self):
|
||||
super(TestCourseSerializerFields, self).setUp()
|
||||
@@ -35,6 +37,35 @@ class TestCourseSerializerFields(CourseApiFactoryMixin, ModuleStoreTestCase):
|
||||
request.user = user
|
||||
return request
|
||||
|
||||
def test_basic(self):
|
||||
expected_data = {
|
||||
'course_id': u'edX/toy/2012_Fall',
|
||||
'name': u'Toy Course',
|
||||
'number': u'toy',
|
||||
'org': u'edX',
|
||||
'short_description': u'A course about toys.',
|
||||
'media': {
|
||||
'course_image': {
|
||||
'uri': u'/c4x/edX/toy/asset/just_a_test.jpg',
|
||||
},
|
||||
'course_video': {
|
||||
'uri': u'http://www.youtube.com/watch?v=test_youtube_id',
|
||||
}
|
||||
},
|
||||
'start': u'2015-07-17T12:00:00Z',
|
||||
'start_type': u'timestamp',
|
||||
'start_display': u'July 17, 2015',
|
||||
'end': u'2015-09-19T18:00:00',
|
||||
'enrollment_start': u'2015-06-15T00:00:00',
|
||||
'enrollment_end': u'2015-07-15T00:00:00',
|
||||
'blocks_url': u'http://testserver/api/courses/v1/blocks/?course_id=edX%2Ftoy%2F2012_Fall',
|
||||
'effort': u'6 hours',
|
||||
}
|
||||
course = self.create_course()
|
||||
CourseDetails.update_about_video(course, 'test_youtube_id', self.staff_user.id) # pylint: disable=no-member
|
||||
result = CourseSerializer(course, context={'request': self._get_request()}).data
|
||||
self.assertDictEqual(result, expected_data)
|
||||
|
||||
def test_advertised_start(self):
|
||||
course = self.create_course(
|
||||
course=u'custom',
|
||||
@@ -52,16 +83,3 @@ class TestCourseSerializerFields(CourseApiFactoryMixin, ModuleStoreTestCase):
|
||||
self.assertEqual(result['course_id'], u'edX/custom/2012_Fall')
|
||||
self.assertEqual(result['start_type'], u'empty')
|
||||
self.assertIsNone(result['start_display'])
|
||||
|
||||
def test_description(self):
|
||||
course = self.create_course()
|
||||
result = CourseSerializer(course, context={'request': self._get_request()}).data
|
||||
self.assertEqual(result['description'], u'A course about toys.')
|
||||
|
||||
def test_blocks_url(self):
|
||||
course = self.create_course()
|
||||
result = CourseSerializer(course, context={'request': self._get_request()}).data
|
||||
self.assertEqual(
|
||||
result['blocks_url'],
|
||||
u'http://testserver/api/courses/v1/blocks/?course_id=edX%2Ftoy%2F2012_Fall'
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user