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
ae439310
Commit
ae439310
authored
Dec 25, 2015
by
lenacom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New optional parameters for course blocks API: lti_url, block_types
parent
46533015
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
52 additions
and
10 deletions
+52
-10
lms/djangoapps/course_api/blocks/api.py
+13
-0
lms/djangoapps/course_api/blocks/forms.py
+2
-0
lms/djangoapps/course_api/blocks/serializers.py
+7
-1
lms/djangoapps/course_api/blocks/tests/test_api.py
+14
-2
lms/djangoapps/course_api/blocks/tests/test_forms.py
+1
-0
lms/djangoapps/course_api/blocks/tests/test_serializers.py
+2
-3
lms/djangoapps/course_api/blocks/views.py
+12
-3
openedx/core/lib/block_structure/block_structure.py
+1
-1
No files found.
lms/djangoapps/course_api/blocks/api.py
View file @
ae439310
...
@@ -20,6 +20,7 @@ def get_blocks(
...
@@ -20,6 +20,7 @@ def get_blocks(
block_counts
=
None
,
block_counts
=
None
,
student_view_data
=
None
,
student_view_data
=
None
,
return_type
=
'dict'
,
return_type
=
'dict'
,
block_types
=
None
):
):
"""
"""
Return a serialized representation of the course blocks.
Return a serialized representation of the course blocks.
...
@@ -61,6 +62,18 @@ def get_blocks(
...
@@ -61,6 +62,18 @@ def get_blocks(
# transform
# transform
blocks
=
get_course_blocks
(
user
,
usage_key
,
transformers
)
blocks
=
get_course_blocks
(
user
,
usage_key
,
transformers
)
# filter blocks by types
if
block_types
and
len
(
block_types
)
==
0
:
block_types
=
None
if
block_types
:
block_keys_to_remove
=
[]
for
block_key
in
blocks
:
block_type
=
blocks
.
get_xblock_field
(
block_key
,
'category'
)
if
not
block_type
in
block_types
:
block_keys_to_remove
.
append
(
block_key
)
for
block_key
in
block_keys_to_remove
:
blocks
.
remove_block
(
block_key
,
True
)
# serialize
# serialize
serializer_context
=
{
serializer_context
=
{
'request'
:
request
,
'request'
:
request
,
...
...
lms/djangoapps/course_api/blocks/forms.py
View file @
ae439310
...
@@ -31,6 +31,7 @@ class BlockListGetForm(Form):
...
@@ -31,6 +31,7 @@ class BlockListGetForm(Form):
student_view_data
=
MultiValueField
(
required
=
False
)
student_view_data
=
MultiValueField
(
required
=
False
)
usage_key
=
CharField
(
required
=
True
)
usage_key
=
CharField
(
required
=
True
)
username
=
CharField
(
required
=
False
)
username
=
CharField
(
required
=
False
)
block_types
=
MultiValueField
(
required
=
False
)
def
clean_depth
(
self
):
def
clean_depth
(
self
):
"""
"""
...
@@ -88,6 +89,7 @@ class BlockListGetForm(Form):
...
@@ -88,6 +89,7 @@ class BlockListGetForm(Form):
'student_view_data'
,
'student_view_data'
,
'block_counts'
,
'block_counts'
,
'nav_depth'
,
'nav_depth'
,
'block_types'
,
]
]
for
additional_field
in
additional_requested_fields
:
for
additional_field
in
additional_requested_fields
:
field_value
=
cleaned_data
.
get
(
additional_field
)
field_value
=
cleaned_data
.
get
(
additional_field
)
...
...
lms/djangoapps/course_api/blocks/serializers.py
View file @
ae439310
...
@@ -44,6 +44,13 @@ class BlockSerializer(serializers.Serializer): # pylint: disable=abstract-metho
...
@@ -44,6 +44,13 @@ class BlockSerializer(serializers.Serializer): # pylint: disable=abstract-metho
),
),
}
}
if
'lti_url'
in
self
.
context
[
'requested_fields'
]:
data
[
'lti_url'
]
=
reverse
(
'lti_provider_launch'
,
kwargs
=
{
'course_id'
:
unicode
(
block_key
.
course_key
),
'usage_id'
:
unicode
(
block_key
)},
request
=
self
.
context
[
'request'
],
)
# add additional requested fields that are supported by the various transformers
# add additional requested fields that are supported by the various transformers
for
supported_field
in
SUPPORTED_FIELDS
:
for
supported_field
in
SUPPORTED_FIELDS
:
if
supported_field
.
requested_field_name
in
self
.
context
[
'requested_fields'
]:
if
supported_field
.
requested_field_name
in
self
.
context
[
'requested_fields'
]:
...
@@ -70,7 +77,6 @@ class BlockDictSerializer(serializers.Serializer): # pylint: disable=abstract-m
...
@@ -70,7 +77,6 @@ class BlockDictSerializer(serializers.Serializer): # pylint: disable=abstract-m
Serializer that formats a BlockStructure object to a dictionary, rather
Serializer that formats a BlockStructure object to a dictionary, rather
than a list, of blocks
than a list, of blocks
"""
"""
root
=
serializers
.
CharField
(
source
=
'root_block_usage_key'
)
blocks
=
serializers
.
SerializerMethodField
()
blocks
=
serializers
.
SerializerMethodField
()
def
get_blocks
(
self
,
structure
):
def
get_blocks
(
self
,
structure
):
...
...
lms/djangoapps/course_api/blocks/tests/test_api.py
View file @
ae439310
...
@@ -35,7 +35,6 @@ class TestGetBlocks(EnableTransformerRegistryMixin, SharedModuleStoreTestCase):
...
@@ -35,7 +35,6 @@ class TestGetBlocks(EnableTransformerRegistryMixin, SharedModuleStoreTestCase):
def
test_basic
(
self
):
def
test_basic
(
self
):
blocks
=
get_blocks
(
self
.
request
,
self
.
course
.
location
,
self
.
user
)
blocks
=
get_blocks
(
self
.
request
,
self
.
course
.
location
,
self
.
user
)
self
.
assertEquals
(
blocks
[
'root'
],
unicode
(
self
.
course
.
location
))
# subtract for (1) the orphaned course About block and (2) the hidden Html block
# subtract for (1) the orphaned course About block and (2) the hidden Html block
self
.
assertEquals
(
len
(
blocks
[
'blocks'
]),
len
(
self
.
store
.
get_items
(
self
.
course
.
id
))
-
2
)
self
.
assertEquals
(
len
(
blocks
[
'blocks'
]),
len
(
self
.
store
.
get_items
(
self
.
course
.
id
))
-
2
)
...
@@ -63,7 +62,6 @@ class TestGetBlocks(EnableTransformerRegistryMixin, SharedModuleStoreTestCase):
...
@@ -63,7 +62,6 @@ class TestGetBlocks(EnableTransformerRegistryMixin, SharedModuleStoreTestCase):
sequential_block
=
self
.
store
.
get_item
(
self
.
course
.
id
.
make_usage_key
(
'sequential'
,
'sequential_y1'
))
sequential_block
=
self
.
store
.
get_item
(
self
.
course
.
id
.
make_usage_key
(
'sequential'
,
'sequential_y1'
))
blocks
=
get_blocks
(
self
.
request
,
sequential_block
.
location
,
self
.
user
)
blocks
=
get_blocks
(
self
.
request
,
sequential_block
.
location
,
self
.
user
)
self
.
assertEquals
(
blocks
[
'root'
],
unicode
(
sequential_block
.
location
))
self
.
assertEquals
(
len
(
blocks
[
'blocks'
]),
5
)
self
.
assertEquals
(
len
(
blocks
[
'blocks'
]),
5
)
for
block_type
,
block_name
,
is_inside_of_structure
in
(
for
block_type
,
block_name
,
is_inside_of_structure
in
(
...
@@ -77,3 +75,17 @@ class TestGetBlocks(EnableTransformerRegistryMixin, SharedModuleStoreTestCase):
...
@@ -77,3 +75,17 @@ class TestGetBlocks(EnableTransformerRegistryMixin, SharedModuleStoreTestCase):
self
.
assertIn
(
unicode
(
block
.
location
),
blocks
[
'blocks'
])
self
.
assertIn
(
unicode
(
block
.
location
),
blocks
[
'blocks'
])
else
:
else
:
self
.
assertNotIn
(
unicode
(
block
.
location
),
blocks
[
'blocks'
])
self
.
assertNotIn
(
unicode
(
block
.
location
),
blocks
[
'blocks'
])
def
test_filtering_by_block_types
(
self
):
sequential_block
=
self
.
store
.
get_item
(
self
.
course
.
id
.
make_usage_key
(
'sequential'
,
'sequential_y1'
))
block_types
=
[
'problem'
]
blocks
=
get_blocks
(
self
.
request
,
sequential_block
.
location
,
self
.
user
,
block_types
=
block_types
)
for
block_type
,
block_name
in
(
(
'problem'
,
'problem_y1a_1'
),
(
'problem'
,
'problem_y1a_2'
),
(
'problem'
,
'problem_y1a_3'
),
):
block
=
self
.
store
.
get_item
(
self
.
course
.
id
.
make_usage_key
(
block_type
,
block_name
))
self
.
assertIn
(
unicode
(
block
.
location
),
blocks
[
'blocks'
])
lms/djangoapps/course_api/blocks/tests/test_forms.py
View file @
ae439310
...
@@ -60,6 +60,7 @@ class TestBlockListGetForm(EnableTransformerRegistryMixin, FormTestMixin, Shared
...
@@ -60,6 +60,7 @@ class TestBlockListGetForm(EnableTransformerRegistryMixin, FormTestMixin, Shared
'usage_key'
:
usage_key
,
'usage_key'
:
usage_key
,
'username'
:
self
.
student
.
username
,
'username'
:
self
.
student
.
username
,
'user'
:
self
.
student
,
'user'
:
self
.
student
,
'block_types'
:
set
(),
}
}
def
assert_raises_permission_denied
(
self
):
def
assert_raises_permission_denied
(
self
):
...
...
lms/djangoapps/course_api/blocks/tests/test_serializers.py
View file @
ae439310
...
@@ -70,6 +70,7 @@ class TestBlockSerializerBase(EnableTransformerRegistryMixin, SharedModuleStoreT
...
@@ -70,6 +70,7 @@ class TestBlockSerializerBase(EnableTransformerRegistryMixin, SharedModuleStoreT
'block_counts'
,
'block_counts'
,
'student_view_data'
,
'student_view_data'
,
'student_view_multi_device'
,
'student_view_multi_device'
,
'lti_url'
,
])
])
def
assert_extended_block
(
self
,
serialized_block
):
def
assert_extended_block
(
self
,
serialized_block
):
...
@@ -81,6 +82,7 @@ class TestBlockSerializerBase(EnableTransformerRegistryMixin, SharedModuleStoreT
...
@@ -81,6 +82,7 @@ class TestBlockSerializerBase(EnableTransformerRegistryMixin, SharedModuleStoreT
'id'
,
'type'
,
'lms_web_url'
,
'student_view_url'
,
'id'
,
'type'
,
'lms_web_url'
,
'student_view_url'
,
'display_name'
,
'graded'
,
'display_name'
,
'graded'
,
'block_counts'
,
'student_view_multi_device'
,
'block_counts'
,
'student_view_multi_device'
,
'lti_url'
,
},
},
set
(
serialized_block
.
iterkeys
()),
set
(
serialized_block
.
iterkeys
()),
)
)
...
@@ -136,9 +138,6 @@ class TestBlockDictSerializer(TestBlockSerializerBase):
...
@@ -136,9 +138,6 @@ class TestBlockDictSerializer(TestBlockSerializerBase):
def
test_basic
(
self
):
def
test_basic
(
self
):
serializer
=
self
.
create_serializer
()
serializer
=
self
.
create_serializer
()
# verify root
self
.
assertEquals
(
serializer
.
data
[
'root'
],
unicode
(
self
.
block_structure
.
root_block_usage_key
))
# verify blocks
# verify blocks
for
block_key_string
,
serialized_block
in
serializer
.
data
[
'blocks'
]
.
iteritems
():
for
block_key_string
,
serialized_block
in
serializer
.
data
[
'blocks'
]
.
iteritems
():
self
.
assertEquals
(
serialized_block
[
'id'
],
block_key_string
)
self
.
assertEquals
(
serialized_block
[
'id'
],
block_key_string
)
...
...
lms/djangoapps/course_api/blocks/views.py
View file @
ae439310
...
@@ -30,9 +30,10 @@ class BlocksView(DeveloperErrorViewMixin, ListAPIView):
...
@@ -30,9 +30,10 @@ class BlocksView(DeveloperErrorViewMixin, ListAPIView):
GET /api/courses/v1/blocks/<usage_id>/?
GET /api/courses/v1/blocks/<usage_id>/?
username=anjali
username=anjali
&depth=all
&depth=all
&requested_fields=graded,format,student_view_multi_device
&requested_fields=graded,format,student_view_multi_device
,lti_url
&block_counts=video
&block_counts=video
&student_view_data=video
&student_view_data=video
&block_types=problem,html
**Parameters**:
**Parameters**:
...
@@ -85,6 +86,11 @@ class BlocksView(DeveloperErrorViewMixin, ListAPIView):
...
@@ -85,6 +86,11 @@ class BlocksView(DeveloperErrorViewMixin, ListAPIView):
Example: return_type=dict
Example: return_type=dict
* block_types: (list) Requested types of blocks. Possible values include sequential,
vertical, html, problem, video, and discussion.
Example: block_types=vertical,html
**Response Values**
**Response Values**
The following fields are returned with a successful response.
The following fields are returned with a successful response.
...
@@ -147,6 +153,7 @@ class BlocksView(DeveloperErrorViewMixin, ListAPIView):
...
@@ -147,6 +153,7 @@ class BlocksView(DeveloperErrorViewMixin, ListAPIView):
if the student_view_url and the student_view_data fields are not
if the student_view_url and the student_view_data fields are not
supported.
supported.
* lti_url: The block URL for an LTI consumer.
"""
"""
def
list
(
self
,
request
,
usage_key_string
):
# pylint: disable=arguments-differ
def
list
(
self
,
request
,
usage_key_string
):
# pylint: disable=arguments-differ
...
@@ -177,7 +184,8 @@ class BlocksView(DeveloperErrorViewMixin, ListAPIView):
...
@@ -177,7 +184,8 @@ class BlocksView(DeveloperErrorViewMixin, ListAPIView):
params
.
cleaned_data
[
'requested_fields'
],
params
.
cleaned_data
[
'requested_fields'
],
params
.
cleaned_data
.
get
(
'block_counts'
,
[]),
params
.
cleaned_data
.
get
(
'block_counts'
,
[]),
params
.
cleaned_data
.
get
(
'student_view_data'
,
[]),
params
.
cleaned_data
.
get
(
'student_view_data'
,
[]),
params
.
cleaned_data
[
'return_type'
]
params
.
cleaned_data
[
'return_type'
],
params
.
cleaned_data
.
get
(
'block_types'
,
None
),
)
)
)
)
except
ItemNotFoundError
as
exception
:
except
ItemNotFoundError
as
exception
:
...
@@ -198,9 +206,10 @@ class BlocksInCourseView(BlocksView):
...
@@ -198,9 +206,10 @@ class BlocksInCourseView(BlocksView):
GET /api/courses/v1/blocks/?course_id=<course_id>
GET /api/courses/v1/blocks/?course_id=<course_id>
&username=anjali
&username=anjali
&depth=all
&depth=all
&requested_fields=graded,format,student_view_multi_device
&requested_fields=graded,format,student_view_multi_device
,lti_url
&block_counts=video
&block_counts=video
&student_view_data=video
&student_view_data=video
&block_types=problem,html
**Parameters**:
**Parameters**:
...
...
openedx/core/lib/block_structure/block_structure.py
View file @
ae439310
...
@@ -70,7 +70,7 @@ class BlockStructure(object):
...
@@ -70,7 +70,7 @@ class BlockStructure(object):
traversal since it's the more common case and we currently
traversal since it's the more common case and we currently
need to support DAGs.
need to support DAGs.
"""
"""
return
self
.
topological_traversal
()
return
self
.
get_block_keys
()
#--- Block structure relation methods ---#
#--- Block structure relation methods ---#
...
...
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