Commit de548fbf by Andy Armstrong

Merge pull request #2216 from edx/andya/move-service

Implement a course outline REST API
parents ef8671ad 89c2f4dd
......@@ -6,7 +6,7 @@ import lxml
from contentstore.tests.utils import CourseTestCase
from xmodule.modulestore.django import loc_mapper
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from xmodule.modulestore import parsers
class TestCourseIndex(CourseTestCase):
......@@ -83,3 +83,49 @@ class TestCourseIndex(CourseTestCase):
# test access
self.check_index_and_outline(course_staff_client)
def test_json_responses(self):
outline_url = self.course_locator.url_reverse('course/')
chapter = ItemFactory.create(parent_location=self.course.location, category='chapter', display_name="Week 1")
lesson = ItemFactory.create(parent_location=chapter.location, category='sequential', display_name="Lesson 1")
subsection = ItemFactory.create(parent_location=lesson.location, category='vertical', display_name='Subsection 1')
ItemFactory.create(parent_location=subsection.location, category="video", display_name="My Video")
resp = self.client.get(outline_url, HTTP_ACCEPT='application/json')
json_response = json.loads(resp.content)
# First spot check some values in the root response
self.assertEqual(json_response['category'], 'course')
self.assertEqual(json_response['id'], 'MITx.999.Robot_Super_Course/branch/draft/block/Robot_Super_Course')
self.assertEqual(json_response['display_name'], 'Robot Super Course')
self.assertTrue(json_response['is_container'])
self.assertFalse(json_response['is_draft'])
# Now verify that the first child
children = json_response['children']
self.assertTrue(len(children) > 0)
first_child_response = children[0]
self.assertEqual(first_child_response['category'], 'chapter')
self.assertEqual(first_child_response['id'], 'MITx.999.Robot_Super_Course/branch/draft/block/Week_1')
self.assertEqual(first_child_response['display_name'], 'Week 1')
self.assertTrue(first_child_response['is_container'])
self.assertFalse(first_child_response['is_draft'])
self.assertTrue(len(first_child_response['children']) > 0)
# Finally, validate the entire response for consistency
self.assert_correct_json_response(json_response)
def assert_correct_json_response(self, json_response):
"""
Asserts that the JSON response is syntactically consistent
"""
self.assertIsNotNone(json_response['display_name'])
self.assertIsNotNone(json_response['id'])
self.assertIsNotNone(json_response['category'])
self.assertIsNotNone(json_response['is_draft'])
self.assertIsNotNone(json_response['is_container'])
if json_response['is_container']:
for child_response in json_response['children']:
self.assert_correct_json_response(child_response)
else:
self.assertFalse('children' in json_response)
......@@ -100,9 +100,10 @@ def course_handler(request, tag=None, package_id=None, branch=None, version_guid
DELETE
json: delete this branch from this course (leaving off /branch/draft would imply delete the course)
"""
if 'application/json' in request.META.get('HTTP_ACCEPT', 'application/json'):
response_format = request.REQUEST.get('format', 'html')
if response_format == 'json' or 'application/json' in request.META.get('HTTP_ACCEPT', 'application/json'):
if request.method == 'GET':
raise NotImplementedError('coming soon')
return JsonResponse(_course_json(request, package_id, branch, version_guid, block))
elif request.method == 'POST': # not sure if this is only post. If one will have ids, it goes after access
return create_new_course(request)
elif not has_course_access(
......@@ -126,6 +127,37 @@ def course_handler(request, tag=None, package_id=None, branch=None, version_guid
@login_required
def _course_json(request, package_id, branch, version_guid, block):
"""
Returns a JSON overview of a course
"""
__, course = _get_locator_and_course(
package_id, branch, version_guid, block, request.user, depth=None
)
return _xmodule_json(course, course.location.course_id)
def _xmodule_json(xmodule, course_id):
"""
Returns a JSON overview of an XModule
"""
locator = loc_mapper().translate_location(
course_id, xmodule.location, published=False, add_entry_if_missing=True
)
is_container = xmodule.has_children
result = {
'display_name': xmodule.display_name,
'id': unicode(locator),
'category': xmodule.category,
'is_draft': getattr(xmodule, 'is_draft', False),
'is_container': is_container,
}
if is_container:
result['children'] = [_xmodule_json(child, course_id) for child in xmodule.get_children()]
return result
@login_required
@ensure_csrf_cookie
def course_listing(request):
"""
......
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