Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
f0b60717
Commit
f0b60717
authored
Jul 01, 2015
by
Jonathan Piacenti
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Courseware Navigation API update for jump_to_children
parent
7ed5672e
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
108 additions
and
17 deletions
+108
-17
lms/djangoapps/api_manager/courses/tests.py
+43
-4
lms/djangoapps/api_manager/courses/urls.py
+1
-0
lms/djangoapps/api_manager/courses/views.py
+47
-2
lms/djangoapps/courseware/views.py
+17
-11
No files found.
lms/djangoapps/api_manager/courses/tests.py
View file @
f0b60717
...
...
@@ -6,6 +6,7 @@ Run these tests @ Devstack:
from
datetime
import
datetime
import
json
import
uuid
from
django.utils
import
timezone
import
mock
from
random
import
randint
from
urllib
import
urlencode
...
...
@@ -23,6 +24,7 @@ from courseware import module_render
from
courseware.tests.factories
import
StudentModuleFactory
from
courseware.model_data
import
FieldDataCache
from
django_comment_common.models
import
Role
,
FORUM_ROLE_MODERATOR
from
gradebook.models
import
StudentGradebook
from
instructor.access
import
allow_access
from
student.tests.factories
import
UserFactory
,
CourseEnrollmentFactory
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
...
...
@@ -92,7 +94,6 @@ class CoursesApiTests(ModuleStoreTestCase):
)
return
module
def
setUp
(
self
):
self
.
test_server_prefix
=
'https://testserver'
self
.
base_courses_uri
=
'/api/server/courses'
...
...
@@ -141,11 +142,32 @@ class CoursesApiTests(ModuleStoreTestCase):
display_name
=
"Video_Sequence"
)
self
.
course_content2
=
ItemFactory
.
create
(
category
=
"sequential"
,
parent_location
=
self
.
chapter
.
location
,
data
=
self
.
test_data
,
display_name
=
"Sequential"
,
)
self
.
content_child
=
ItemFactory
.
create
(
category
=
"video"
,
parent_location
=
self
.
course_content
.
location
,
data
=
self
.
test_data
,
display_name
=
"Video_Resources"
display_name
=
"Video"
)
self
.
content_child2
=
ItemFactory
.
create
(
category
=
"vertical"
,
parent_location
=
self
.
course_content2
.
location
,
data
=
self
.
test_data
,
display_name
=
"Vertical Sequence"
)
self
.
content_subchild
=
ItemFactory
.
create
(
category
=
"video"
,
parent_location
=
self
.
content_child2
.
location
,
data
=
self
.
test_data
,
display_name
=
"Child Video"
,
)
self
.
overview
=
ItemFactory
.
create
(
...
...
@@ -330,7 +352,6 @@ class CoursesApiTests(ModuleStoreTestCase):
self
.
assertIsNotNone
(
course
[
'course_image_url'
])
self
.
assertItemsEqual
(
courses
,
courses_in_result
)
def
test_course_detail_without_date_values
(
self
):
create_course_with_out_date_values
=
CourseFactory
.
create
()
# pylint: disable=C0103
test_uri
=
self
.
base_courses_uri
+
'/'
+
unicode
(
create_course_with_out_date_values
.
id
)
...
...
@@ -387,7 +408,7 @@ class CoursesApiTests(ModuleStoreTestCase):
chapter
=
response
.
data
[
'content'
][
0
]
self
.
assertEqual
(
chapter
[
'category'
],
'chapter'
)
self
.
assertEqual
(
chapter
[
'name'
],
'Overview'
)
self
.
assertEqual
(
len
(
chapter
[
'children'
]),
5
)
self
.
assertEqual
(
len
(
chapter
[
'children'
]),
6
)
sequence
=
chapter
[
'children'
][
0
]
self
.
assertEqual
(
sequence
[
'category'
],
'videosequence'
)
...
...
@@ -2456,3 +2477,21 @@ class CoursesApiTests(ModuleStoreTestCase):
delete_uri
=
'{}invalid_role/users/{}'
.
format
(
test_uri
,
self
.
users
[
0
]
.
id
)
response
=
self
.
do_delete
(
delete_uri
)
self
.
assertEqual
(
response
.
status_code
,
404
)
def
test_course_navigation
(
self
):
test_uri
=
'{}/{}/navigation/{}'
.
format
(
self
.
base_courses_uri
,
unicode
(
self
.
course
.
id
),
self
.
content_subchild
.
location
.
block_id
)
response
=
self
.
do_get
(
test_uri
)
self
.
maxDiff
=
None
self
.
assertEqual
(
{
'chapter'
:
unicode
(
self
.
chapter
.
location
),
'vertical'
:
unicode
(
self
.
content_child2
.
location
),
'section'
:
unicode
(
self
.
course_content2
.
location
),
'course_key'
:
unicode
(
self
.
course
.
id
),
'final_target_id'
:
unicode
(
self
.
content_subchild
.
location
),
'position'
:
'1'
,
},
response
.
data
)
lms/djangoapps/api_manager/courses/urls.py
View file @
f0b60717
...
...
@@ -40,6 +40,7 @@ urlpatterns = patterns(
url
(
r'^{0}/users/(?P<user_id>[0-9]+)$'
.
format
(
COURSE_ID_PATTERN
),
courses_views
.
CoursesUsersDetail
.
as_view
()),
url
(
r'^{0}/users/*$'
.
format
(
COURSE_ID_PATTERN
),
courses_views
.
CoursesUsersList
.
as_view
()),
url
(
r'^{0}/workgroups/*$'
.
format
(
COURSE_ID_PATTERN
),
courses_views
.
CoursesWorkgroupsList
.
as_view
()),
url
(
r'^{0}/navigation/{1}$'
.
format
(
COURSE_ID_PATTERN
,
settings
.
USAGE_KEY_PATTERN
),
courses_views
.
CourseNavView
.
as_view
()),
url
(
r'^{0}$'
.
format
(
COURSE_ID_PATTERN
),
courses_views
.
CoursesDetail
.
as_view
()),
url
(
r'/*$^'
,
courses_views
.
CoursesList
.
as_view
()),
)
...
...
lms/djangoapps/api_manager/courses/views.py
View file @
f0b60717
...
...
@@ -21,7 +21,7 @@ from rest_framework.response import Response
from
courseware.courses
import
get_course_about_section
,
get_course_info_section
,
course_image_url
from
courseware.models
import
StudentModule
from
courseware.views
import
get_static_tab_contents
from
courseware.views
import
get_static_tab_contents
,
item_finder
from
django_comment_common.models
import
FORUM_ROLE_MODERATOR
from
gradebook.models
import
StudentGradebook
from
instructor.access
import
revoke_access
,
update_forum_role
...
...
@@ -29,13 +29,14 @@ from lms.lib.comment_client.user import get_course_social_stats
from
lms.lib.comment_client.thread
import
get_course_thread_stats
from
lms.lib.comment_client.utils
import
CommentClientRequestError
from
opaque_keys
import
InvalidKeyError
from
opaque_keys.edx.keys
import
CourseKey
from
opaque_keys.edx.keys
import
CourseKey
,
UsageKey
from
progress.models
import
StudentProgress
from
projects.models
import
Project
,
Workgroup
from
projects.serializers
import
ProjectSerializer
,
BasicWorkgroupSerializer
from
student.models
import
CourseEnrollment
,
CourseEnrollmentAllowed
from
student.roles
import
CourseRole
,
CourseAccessRole
,
CourseInstructorRole
,
CourseStaffRole
,
CourseObserverRole
,
CourseAssistantRole
,
UserBasedRole
,
get_aggregate_exclusion_user_ids
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.search
import
path_to_location
from
api_manager.courseware_access
import
get_course
,
get_course_child
,
get_course_leaf_nodes
,
get_course_key
,
\
course_exists
,
get_modulestore
,
get_course_descriptor
...
...
@@ -1961,3 +1962,47 @@ class CoursesRolesUsersDetail(SecureAPIView):
return
Response
({},
status
=
status
.
HTTP_404_NOT_FOUND
)
return
Response
({},
status
=
status
.
HTTP_204_NO_CONTENT
)
class
CourseNavView
(
SecureAPIView
):
"""
### The CourseNavView view exposes navigation information for particular usage id: course, chapter, section and
vertical keys, position in innermost container and last addressable block/module on the path (usually the same
usage id that was passed as an argument)
- URI: ```/api/courses/{course_id}/navigation/{module_id}```
- GET: Gets navigation information
"""
def
_get_full_location_key_by_module_id
(
self
,
request
,
course_key
,
module_id
):
"""
Gets full location id by module id
"""
items
=
item_finder
(
request
,
course_key
,
module_id
)
return
items
[
0
]
.
location
def
get
(
self
,
request
,
course_id
,
usage_key_string
):
# pylint: disable=W0613
"""
GET /api/courses/{course_id}/navigation/{module_id}
"""
try
:
_
,
course_key
,
__
=
get_course
(
request
,
request
.
user
,
course_id
)
usage_key
=
self
.
_get_full_location_key_by_module_id
(
request
,
course_key
,
usage_key_string
)
except
InvalidKeyError
:
raise
Http404
(
u"Invalid course_key or usage_key"
)
(
course_key
,
chapter
,
section
,
vertical
,
position
,
final_target_id
)
=
path_to_location
(
modulestore
(),
usage_key
)
chapter_key
=
course_key
.
make_usage_key
(
'chapter'
,
chapter
)
section_key
=
course_key
.
make_usage_key
(
'sequential'
,
section
)
vertical_key
=
course_key
.
make_usage_key
(
'vertical'
,
vertical
)
result
=
{
'course_key'
:
unicode
(
course_key
),
'chapter'
:
unicode
(
chapter_key
),
'section'
:
unicode
(
section_key
),
'vertical'
:
unicode
(
vertical_key
),
'position'
:
unicode
(
position
),
'final_target_id'
:
unicode
(
final_target_id
)
}
return
Response
(
result
,
status
=
status
.
HTTP_200_OK
)
lms/djangoapps/courseware/views.py
View file @
f0b60717
...
...
@@ -623,28 +623,34 @@ def _index_bulk_op(request, course_key, chapter, section, position):
return
result
@ensure_csrf_cookie
@ensure_valid_course_key
def
jump_to_id
(
request
,
course_id
,
module_id
):
"""
This entry point allows for a shorter version of a jump to where just the id of the element is
passed in. This assumes that id is unique within the course_id namespace
"""
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
def
item_finder
(
request
,
course_key
,
module_id
):
items
=
modulestore
()
.
get_items
(
course_key
,
qualifiers
=
{
'name'
:
module_id
})
if
len
(
items
)
==
0
:
raise
Http404
(
u"Could not find id: {0} in course_id: {1}. Referer: {2}"
.
format
(
module_id
,
course_
id
,
request
.
META
.
get
(
"HTTP_REFERER"
,
""
)
module_id
,
course_
key
,
request
.
META
.
get
(
"HTTP_REFERER"
,
""
)
))
if
len
(
items
)
>
1
:
log
.
warning
(
u"Multiple items found with id: {0} in course_id: {1}. Referer: {2}. Using first: {3}"
.
format
(
module_id
,
course_
id
,
request
.
META
.
get
(
"HTTP_REFERER"
,
""
),
items
[
0
]
.
location
.
to_deprecated_string
()
module_id
,
course_
key
,
request
.
META
.
get
(
"HTTP_REFERER"
,
""
),
items
[
0
]
.
location
.
to_deprecated_string
()
))
return
jump_to
(
request
,
course_id
,
items
[
0
]
.
location
.
to_deprecated_string
())
return
items
@ensure_csrf_cookie
@ensure_valid_course_key
def
jump_to_id
(
request
,
course_id
,
module_id
):
"""
This entry point allows for a shorter version of a jump to where just the id of the element is
passed in. This assumes that id is unique within the course_id namespace
"""
course_key
=
CourseKey
.
from_string
(
course_id
)
items
=
item_finder
(
request
,
course_key
,
module_id
)
return
jump_to
(
request
,
course_id
,
unicode
(
items
[
0
]
.
location
))
@ensure_csrf_cookie
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment