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
3893a9ae
Commit
3893a9ae
authored
Jul 02, 2014
by
Calen Pennington
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4258 from cpennington/studio-deprecated-urls
Make Studio able to handle deprecated key formats in urls
parents
0765fbb4
1c882da3
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
97 additions
and
82 deletions
+97
-82
cms/djangoapps/contentstore/tests/test_contentstore.py
+1
-32
cms/djangoapps/contentstore/tests/test_import.py
+1
-1
cms/djangoapps/contentstore/views/component.py
+7
-7
cms/djangoapps/contentstore/views/item.py
+14
-14
cms/djangoapps/contentstore/views/tests/test_course_index.py
+2
-1
cms/djangoapps/contentstore/views/tests/test_item.py
+4
-1
cms/urls.py
+26
-22
common/lib/xmodule/xmodule/modulestore/mongo/base.py
+42
-4
No files found.
cms/djangoapps/contentstore/tests/test_contentstore.py
View file @
3893a9ae
...
@@ -131,7 +131,6 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
...
@@ -131,7 +131,6 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
descriptor
=
store
.
get_items
(
course
.
id
,
category
=
'vertical'
,)
descriptor
=
store
.
get_items
(
course
.
id
,
category
=
'vertical'
,)
resp
=
self
.
client
.
get_html
(
get_url
(
'unit_handler'
,
descriptor
[
0
]
.
location
))
resp
=
self
.
client
.
get_html
(
get_url
(
'unit_handler'
,
descriptor
[
0
]
.
location
))
self
.
assertEqual
(
resp
.
status_code
,
200
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
_test_no_locations
(
self
,
resp
)
for
expected
in
expected_types
:
for
expected
in
expected_types
:
self
.
assertIn
(
expected
,
resp
.
content
)
self
.
assertIn
(
expected
,
resp
.
content
)
...
@@ -157,7 +156,6 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
...
@@ -157,7 +156,6 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
resp
=
self
.
client
.
get_html
(
get_url
(
'unit_handler'
,
usage_key
))
resp
=
self
.
client
.
get_html
(
get_url
(
'unit_handler'
,
usage_key
))
self
.
assertEqual
(
resp
.
status_code
,
400
)
self
.
assertEqual
(
resp
.
status_code
,
400
)
_test_no_locations
(
self
,
resp
,
status_code
=
400
)
def
check_edit_unit
(
self
,
test_course_name
):
def
check_edit_unit
(
self
,
test_course_name
):
_
,
course_items
=
import_from_xml
(
modulestore
(),
self
.
user
.
id
,
'common/test/data/'
,
[
test_course_name
])
_
,
course_items
=
import_from_xml
(
modulestore
(),
self
.
user
.
id
,
'common/test/data/'
,
[
test_course_name
])
...
@@ -364,8 +362,6 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
...
@@ -364,8 +362,6 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
get_url
(
'xblock_view_handler'
,
usage_key
,
kwargs
=
{
'view_name'
:
'container_preview'
})
get_url
(
'xblock_view_handler'
,
usage_key
,
kwargs
=
{
'view_name'
:
'container_preview'
})
)
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
# TODO: uncomment when preview no longer has locations being returned.
# _test_no_locations(self, resp)
# These are the data-ids of the xblocks contained in the vertical.
# These are the data-ids of the xblocks contained in the vertical.
self
.
assertContains
(
resp
,
'edX+toy+2012_Fall+video+sample_video'
)
self
.
assertContains
(
resp
,
'edX+toy+2012_Fall+video+sample_video'
)
...
@@ -534,7 +530,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
...
@@ -534,7 +530,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
url
=
reverse_course_url
(
url
=
reverse_course_url
(
'assets_handler'
,
'assets_handler'
,
course
.
id
,
course
.
id
,
kwargs
=
{
'asset_key_string'
:
course
.
id
.
make_asset_key
(
'asset'
,
'sample_static.txt'
)}
kwargs
=
{
'asset_key_string'
:
unicode
(
course
.
id
.
make_asset_key
(
'asset'
,
'sample_static.txt'
)
)}
)
)
resp
=
self
.
client
.
delete
(
url
)
resp
=
self
.
client
.
delete
(
url
)
self
.
assertEqual
(
resp
.
status_code
,
204
)
self
.
assertEqual
(
resp
.
status_code
,
204
)
...
@@ -761,7 +757,6 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
...
@@ -761,7 +757,6 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
def
test_bad_contentstore_request
(
self
):
def
test_bad_contentstore_request
(
self
):
resp
=
self
.
client
.
get_html
(
'http://localhost:8001/c4x/CDX/123123/asset/&images_circuits_Lab7Solution2.png'
)
resp
=
self
.
client
.
get_html
(
'http://localhost:8001/c4x/CDX/123123/asset/&images_circuits_Lab7Solution2.png'
)
self
.
assertEqual
(
resp
.
status_code
,
400
)
self
.
assertEqual
(
resp
.
status_code
,
400
)
_test_no_locations
(
self
,
resp
,
400
)
def
test_rewrite_nonportable_links_on_import
(
self
):
def
test_rewrite_nonportable_links_on_import
(
self
):
module_store
=
modulestore
()
module_store
=
modulestore
()
...
@@ -1196,7 +1191,6 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
...
@@ -1196,7 +1191,6 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
for
descriptor
in
items
:
for
descriptor
in
items
:
resp
=
self
.
client
.
get_html
(
get_url
(
'unit_handler'
,
descriptor
.
location
))
resp
=
self
.
client
.
get_html
(
get_url
(
'unit_handler'
,
descriptor
.
location
))
self
.
assertEqual
(
resp
.
status_code
,
200
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
_test_no_locations
(
self
,
resp
)
class
ContentStoreTest
(
ContentStoreTestCase
):
class
ContentStoreTest
(
ContentStoreTestCase
):
...
@@ -1475,7 +1469,6 @@ class ContentStoreTest(ContentStoreTestCase):
...
@@ -1475,7 +1469,6 @@ class ContentStoreTest(ContentStoreTestCase):
status_code
=
200
,
status_code
=
200
,
html
=
True
html
=
True
)
)
_test_no_locations
(
self
,
resp
)
def
test_course_factory
(
self
):
def
test_course_factory
(
self
):
"""Test that the course factory works correctly."""
"""Test that the course factory works correctly."""
...
@@ -1498,7 +1491,6 @@ class ContentStoreTest(ContentStoreTestCase):
...
@@ -1498,7 +1491,6 @@ class ContentStoreTest(ContentStoreTestCase):
status_code
=
200
,
status_code
=
200
,
html
=
True
html
=
True
)
)
_test_no_locations
(
self
,
resp
)
def
test_course_overview_view_with_course
(
self
):
def
test_course_overview_view_with_course
(
self
):
"""Test viewing the course overview page with an existing course"""
"""Test viewing the course overview page with an existing course"""
...
@@ -1522,7 +1514,6 @@ class ContentStoreTest(ContentStoreTestCase):
...
@@ -1522,7 +1514,6 @@ class ContentStoreTest(ContentStoreTestCase):
}
}
resp
=
self
.
client
.
ajax_post
(
reverse_url
(
'xblock_handler'
),
section_data
)
resp
=
self
.
client
.
ajax_post
(
reverse_url
(
'xblock_handler'
),
section_data
)
_test_no_locations
(
self
,
resp
,
html
=
False
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
data
=
parse_json
(
resp
)
data
=
parse_json
(
resp
)
...
@@ -1563,7 +1554,6 @@ class ContentStoreTest(ContentStoreTestCase):
...
@@ -1563,7 +1554,6 @@ class ContentStoreTest(ContentStoreTestCase):
get_url
(
handler
,
course_key
,
'course_key_string'
)
get_url
(
handler
,
course_key
,
'course_key_string'
)
)
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
_test_no_locations
(
self
,
resp
)
_
,
course_items
=
import_from_xml
(
modulestore
(),
self
.
user
.
id
,
'common/test/data/'
,
[
'simple'
])
_
,
course_items
=
import_from_xml
(
modulestore
(),
self
.
user
.
id
,
'common/test/data/'
,
[
'simple'
])
course_key
=
course_items
[
0
]
.
id
course_key
=
course_items
[
0
]
.
id
...
@@ -1589,20 +1579,17 @@ class ContentStoreTest(ContentStoreTestCase):
...
@@ -1589,20 +1579,17 @@ class ContentStoreTest(ContentStoreTestCase):
subsection_key
=
course_key
.
make_usage_key
(
'sequential'
,
'test_sequence'
)
subsection_key
=
course_key
.
make_usage_key
(
'sequential'
,
'test_sequence'
)
resp
=
self
.
client
.
get_html
(
get_url
(
'subsection_handler'
,
subsection_key
))
resp
=
self
.
client
.
get_html
(
get_url
(
'subsection_handler'
,
subsection_key
))
self
.
assertEqual
(
resp
.
status_code
,
200
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
_test_no_locations
(
self
,
resp
)
# go look at the Edit page
# go look at the Edit page
unit_key
=
course_key
.
make_usage_key
(
'vertical'
,
'test_vertical'
)
unit_key
=
course_key
.
make_usage_key
(
'vertical'
,
'test_vertical'
)
resp
=
self
.
client
.
get_html
(
get_url
(
'unit_handler'
,
unit_key
))
resp
=
self
.
client
.
get_html
(
get_url
(
'unit_handler'
,
unit_key
))
self
.
assertEqual
(
resp
.
status_code
,
200
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
_test_no_locations
(
self
,
resp
)
def
delete_item
(
category
,
name
):
def
delete_item
(
category
,
name
):
""" Helper method for testing the deletion of an xblock item. """
""" Helper method for testing the deletion of an xblock item. """
item_key
=
course_key
.
make_usage_key
(
category
,
name
)
item_key
=
course_key
.
make_usage_key
(
category
,
name
)
resp
=
self
.
client
.
delete
(
get_url
(
'xblock_handler'
,
item_key
))
resp
=
self
.
client
.
delete
(
get_url
(
'xblock_handler'
,
item_key
))
self
.
assertEqual
(
resp
.
status_code
,
204
)
self
.
assertEqual
(
resp
.
status_code
,
204
)
_test_no_locations
(
self
,
resp
,
status_code
=
204
,
html
=
False
)
# delete a component
# delete a component
delete_item
(
category
=
'html'
,
name
=
'test_html'
)
delete_item
(
category
=
'html'
,
name
=
'test_html'
)
...
@@ -1805,7 +1792,6 @@ class ContentStoreTest(ContentStoreTestCase):
...
@@ -1805,7 +1792,6 @@ class ContentStoreTest(ContentStoreTestCase):
Show the course overview page.
Show the course overview page.
"""
"""
resp
=
self
.
client
.
get_html
(
get_url
(
'course_handler'
,
course_key
,
'course_key_string'
))
resp
=
self
.
client
.
get_html
(
get_url
(
'course_handler'
,
course_key
,
'course_key_string'
))
_test_no_locations
(
self
,
resp
)
return
resp
return
resp
def
test_wiki_slug
(
self
):
def
test_wiki_slug
(
self
):
...
@@ -1887,7 +1873,6 @@ class EntryPageTestCase(TestCase):
...
@@ -1887,7 +1873,6 @@ class EntryPageTestCase(TestCase):
def
_test_page
(
self
,
page
,
status_code
=
200
):
def
_test_page
(
self
,
page
,
status_code
=
200
):
resp
=
self
.
client
.
get_html
(
page
)
resp
=
self
.
client
.
get_html
(
page
)
self
.
assertEqual
(
resp
.
status_code
,
status_code
)
self
.
assertEqual
(
resp
.
status_code
,
status_code
)
_test_no_locations
(
self
,
resp
,
status_code
)
def
test_how_it_works
(
self
):
def
test_how_it_works
(
self
):
self
.
_test_page
(
"/howitworks"
)
self
.
_test_page
(
"/howitworks"
)
...
@@ -1925,19 +1910,3 @@ def _course_factory_create_course():
...
@@ -1925,19 +1910,3 @@ def _course_factory_create_course():
def
_get_course_id
(
course_data
):
def
_get_course_id
(
course_data
):
"""Returns the course ID (org/number/run)."""
"""Returns the course ID (org/number/run)."""
return
SlashSeparatedCourseKey
(
course_data
[
'org'
],
course_data
[
'number'
],
course_data
[
'run'
])
return
SlashSeparatedCourseKey
(
course_data
[
'org'
],
course_data
[
'number'
],
course_data
[
'run'
])
def
_test_no_locations
(
test
,
resp
,
status_code
=
200
,
html
=
True
):
"""
Verifies that "i4x", which appears in old locations, but not
new locators, does not appear in the HTML response output.
Used to verify that database refactoring is complete.
"""
test
.
assertNotContains
(
resp
,
'i4x'
,
status_code
=
status_code
,
html
=
html
)
if
html
:
# For HTML pages, it is nice to call the method with html=True because
# it checks that the HTML properly parses. However, it won't find i4x usages
# in JavaScript blocks.
content
=
resp
.
content
hits
=
len
(
re
.
findall
(
r"(?<!jump_to/)i4x://"
,
content
))
test
.
assertEqual
(
hits
,
0
,
"i4x found outside of LMS jump-to links"
)
cms/djangoapps/contentstore/tests/test_import.py
View file @
3893a9ae
...
@@ -189,7 +189,7 @@ class ContentStoreImportTest(ModuleStoreTestCase):
...
@@ -189,7 +189,7 @@ class ContentStoreImportTest(ModuleStoreTestCase):
target_course_id
.
make_usage_key
(
'conditional'
,
'condone'
)
target_course_id
.
make_usage_key
(
'conditional'
,
'condone'
)
)
)
self
.
assertIsNotNone
(
conditional_module
)
self
.
assertIsNotNone
(
conditional_module
)
different_course_id
=
SlashSeparatedCourseKey
(
'edX'
,
'different_course'
,
'copy_run'
)
different_course_id
=
SlashSeparatedCourseKey
(
'edX'
,
'different_course'
,
None
)
self
.
assertListEqual
(
self
.
assertListEqual
(
[
[
target_course_id
.
make_usage_key
(
'problem'
,
'choiceprob'
),
target_course_id
.
make_usage_key
(
'problem'
,
'choiceprob'
),
...
...
cms/djangoapps/contentstore/views/component.py
View file @
3893a9ae
...
@@ -61,7 +61,7 @@ else:
...
@@ -61,7 +61,7 @@ else:
# XBlocks from pmitros repos are prototypes. They should not be used
# XBlocks from pmitros repos are prototypes. They should not be used
# except for edX Learning Sciences experiments on edge.edx.org without
# except for edX Learning Sciences experiments on edge.edx.org without
# further work to make them robust, maintainable, finalize data formats,
# further work to make them robust, maintainable, finalize data formats,
# etc.
# etc.
'concept'
,
# Concept mapper. See https://github.com/pmitros/ConceptXBlock
'concept'
,
# Concept mapper. See https://github.com/pmitros/ConceptXBlock
'done'
,
# Lets students mark things as done. See https://github.com/pmitros/DoneXBlock
'done'
,
# Lets students mark things as done. See https://github.com/pmitros/DoneXBlock
'audio'
,
# Embed an audio file. See https://github.com/pmitros/AudioXBlock
'audio'
,
# Embed an audio file. See https://github.com/pmitros/AudioXBlock
...
@@ -97,7 +97,7 @@ def subsection_handler(request, usage_key_string):
...
@@ -97,7 +97,7 @@ def subsection_handler(request, usage_key_string):
except
ItemNotFoundError
:
except
ItemNotFoundError
:
return
HttpResponseBadRequest
()
return
HttpResponseBadRequest
()
preview_link
=
get_lms_link_for_item
(
usage_key
,
preview
=
True
)
preview_link
=
get_lms_link_for_item
(
item
.
location
,
preview
=
True
)
# make sure that location references a 'sequential', otherwise return
# make sure that location references a 'sequential', otherwise return
# BadRequest
# BadRequest
...
@@ -134,9 +134,9 @@ def subsection_handler(request, usage_key_string):
...
@@ -134,9 +134,9 @@ def subsection_handler(request, usage_key_string):
'new_unit_category'
:
'vertical'
,
'new_unit_category'
:
'vertical'
,
'lms_link'
:
lms_link
,
'lms_link'
:
lms_link
,
'preview_link'
:
preview_link
,
'preview_link'
:
preview_link
,
'course_graders'
:
json
.
dumps
(
CourseGradingModel
.
fetch
(
usage_key
.
course_key
)
.
graders
),
'course_graders'
:
json
.
dumps
(
CourseGradingModel
.
fetch
(
item
.
location
.
course_key
)
.
graders
),
'parent_item'
:
parent
,
'parent_item'
:
parent
,
'locator'
:
usage_key
,
'locator'
:
item
.
location
,
'policy_metadata'
:
policy_metadata
,
'policy_metadata'
:
policy_metadata
,
'subsection_units'
:
subsection_units
,
'subsection_units'
:
subsection_units
,
'can_view_live'
:
can_view_live
'can_view_live'
:
can_view_live
...
@@ -211,7 +211,7 @@ def unit_handler(request, usage_key_string):
...
@@ -211,7 +211,7 @@ def unit_handler(request, usage_key_string):
return
render_to_response
(
'unit.html'
,
{
return
render_to_response
(
'unit.html'
,
{
'context_course'
:
course
,
'context_course'
:
course
,
'unit'
:
item
,
'unit'
:
item
,
'unit_usage_key'
:
usage_key
,
'unit_usage_key'
:
item
.
location
,
'child_usage_keys'
:
[
block
.
scope_ids
.
usage_id
for
block
in
xblocks
],
'child_usage_keys'
:
[
block
.
scope_ids
.
usage_id
for
block
in
xblocks
],
'component_templates'
:
json
.
dumps
(
component_templates
),
'component_templates'
:
json
.
dumps
(
component_templates
),
'draft_preview_link'
:
preview_lms_link
,
'draft_preview_link'
:
preview_lms_link
,
...
@@ -267,7 +267,7 @@ def container_handler(request, usage_key_string):
...
@@ -267,7 +267,7 @@ def container_handler(request, usage_key_string):
'context_course'
:
course
,
# Needed only for display of menus at top of page.
'context_course'
:
course
,
# Needed only for display of menus at top of page.
'xblock'
:
xblock
,
'xblock'
:
xblock
,
'unit_publish_state'
:
unit_publish_state
,
'unit_publish_state'
:
unit_publish_state
,
'xblock_locator'
:
usage_key
,
'xblock_locator'
:
xblock
.
location
,
'unit'
:
None
if
not
ancestor_xblocks
else
ancestor_xblocks
[
0
],
'unit'
:
None
if
not
ancestor_xblocks
else
ancestor_xblocks
[
0
],
'ancestor_xblocks'
:
ancestor_xblocks
,
'ancestor_xblocks'
:
ancestor_xblocks
,
'component_templates'
:
json
.
dumps
(
component_templates
),
'component_templates'
:
json
.
dumps
(
component_templates
),
...
@@ -415,7 +415,7 @@ def _get_item_in_course(request, usage_key):
...
@@ -415,7 +415,7 @@ def _get_item_in_course(request, usage_key):
course
=
modulestore
()
.
get_course
(
course_key
)
course
=
modulestore
()
.
get_course
(
course_key
)
item
=
modulestore
()
.
get_item
(
usage_key
,
depth
=
1
)
item
=
modulestore
()
.
get_item
(
usage_key
,
depth
=
1
)
lms_link
=
get_lms_link_for_item
(
usage_key
)
lms_link
=
get_lms_link_for_item
(
item
.
location
)
return
course
,
item
,
lms_link
return
course
,
item
,
lms_link
...
...
cms/djangoapps/contentstore/views/item.py
View file @
3893a9ae
...
@@ -144,7 +144,7 @@ def xblock_handler(request, usage_key_string):
...
@@ -144,7 +144,7 @@ def xblock_handler(request, usage_key_string):
request
.
user
,
request
.
user
,
)
)
return
JsonResponse
({
"locator"
:
unicode
(
dest_usage_key
)})
return
JsonResponse
({
"locator"
:
unicode
(
dest_usage_key
)
,
"courseKey"
:
unicode
(
dest_usage_key
.
course_key
)
})
else
:
else
:
return
_create_item
(
request
)
return
_create_item
(
request
)
else
:
else
:
...
@@ -403,7 +403,7 @@ def _create_item(request):
...
@@ -403,7 +403,7 @@ def _create_item(request):
if
display_name
is
not
None
:
if
display_name
is
not
None
:
metadata
[
'display_name'
]
=
display_name
metadata
[
'display_name'
]
=
display_name
store
.
create_and_save_xmodule
(
created_block
=
store
.
create_and_save_xmodule
(
dest_usage_key
,
dest_usage_key
,
request
.
user
.
id
,
request
.
user
.
id
,
definition_data
=
data
,
definition_data
=
data
,
...
@@ -426,10 +426,10 @@ def _create_item(request):
...
@@ -426,10 +426,10 @@ def _create_item(request):
# TODO replace w/ nicer accessor
# TODO replace w/ nicer accessor
if
not
'detached'
in
parent
.
runtime
.
load_block_type
(
category
)
.
_class_tags
:
if
not
'detached'
in
parent
.
runtime
.
load_block_type
(
category
)
.
_class_tags
:
parent
.
children
.
append
(
dest_usage_key
)
parent
.
children
.
append
(
created_block
.
location
)
store
.
update_item
(
parent
,
request
.
user
.
id
)
store
.
update_item
(
parent
,
request
.
user
.
id
)
return
JsonResponse
({
"locator"
:
unicode
(
dest_usage_key
),
"courseKey"
:
unicode
(
dest_usage_key
.
course_key
)})
return
JsonResponse
({
"locator"
:
unicode
(
created_block
.
location
),
"courseKey"
:
unicode
(
created_block
.
location
.
course_key
)})
def
_duplicate_item
(
parent_usage_key
,
duplicate_source_usage_key
,
display_name
=
None
,
user
=
None
):
def
_duplicate_item
(
parent_usage_key
,
duplicate_source_usage_key
,
display_name
=
None
,
user
=
None
):
...
@@ -439,8 +439,8 @@ def _duplicate_item(parent_usage_key, duplicate_source_usage_key, display_name=N
...
@@ -439,8 +439,8 @@ def _duplicate_item(parent_usage_key, duplicate_source_usage_key, display_name=N
store
=
modulestore
()
store
=
modulestore
()
source_item
=
store
.
get_item
(
duplicate_source_usage_key
)
source_item
=
store
.
get_item
(
duplicate_source_usage_key
)
# Change the blockID to be unique.
# Change the blockID to be unique.
dest_usage_key
=
duplicate_source_usage_key
.
replace
(
name
=
uuid4
()
.
hex
)
dest_usage_key
=
source_item
.
location
.
replace
(
name
=
uuid4
()
.
hex
)
category
=
dest_usage_key
.
category
category
=
dest_usage_key
.
block_type
# Update the display name to indicate this is a duplicate (unless display name provided).
# Update the display name to indicate this is a duplicate (unless display name provided).
duplicate_metadata
=
own_metadata
(
source_item
)
duplicate_metadata
=
own_metadata
(
source_item
)
...
@@ -465,7 +465,7 @@ def _duplicate_item(parent_usage_key, duplicate_source_usage_key, display_name=N
...
@@ -465,7 +465,7 @@ def _duplicate_item(parent_usage_key, duplicate_source_usage_key, display_name=N
if
source_item
.
has_children
:
if
source_item
.
has_children
:
dest_module
.
children
=
[]
dest_module
.
children
=
[]
for
child
in
source_item
.
children
:
for
child
in
source_item
.
children
:
dupe
=
_duplicate_item
(
dest_
usage_key
,
child
,
user
=
user
)
dupe
=
_duplicate_item
(
dest_
module
.
location
,
child
,
user
=
user
)
dest_module
.
children
.
append
(
dupe
)
dest_module
.
children
.
append
(
dupe
)
store
.
update_item
(
dest_module
,
user
.
id
if
user
else
None
)
store
.
update_item
(
dest_module
,
user
.
id
if
user
else
None
)
...
@@ -473,14 +473,14 @@ def _duplicate_item(parent_usage_key, duplicate_source_usage_key, display_name=N
...
@@ -473,14 +473,14 @@ def _duplicate_item(parent_usage_key, duplicate_source_usage_key, display_name=N
parent
=
store
.
get_item
(
parent_usage_key
)
parent
=
store
.
get_item
(
parent_usage_key
)
# If source was already a child of the parent, add duplicate immediately afterward.
# If source was already a child of the parent, add duplicate immediately afterward.
# Otherwise, add child to end.
# Otherwise, add child to end.
if
duplicate_source_usage_key
in
parent
.
children
:
if
source_item
.
location
in
parent
.
children
:
source_index
=
parent
.
children
.
index
(
duplicate_source_usage_key
)
source_index
=
parent
.
children
.
index
(
source_item
.
location
)
parent
.
children
.
insert
(
source_index
+
1
,
dest_
usage_key
)
parent
.
children
.
insert
(
source_index
+
1
,
dest_
module
.
location
)
else
:
else
:
parent
.
children
.
append
(
dest_
usage_key
)
parent
.
children
.
append
(
dest_
module
.
location
)
store
.
update_item
(
parent
,
user
.
id
if
user
else
None
)
store
.
update_item
(
parent
,
user
.
id
if
user
else
None
)
return
dest_
usage_key
return
dest_
module
.
location
def
_delete_item
(
usage_key
,
user
):
def
_delete_item
(
usage_key
,
user
):
...
@@ -553,12 +553,12 @@ def _get_module_info(usage_key, user, rewrite_static_links=True):
...
@@ -553,12 +553,12 @@ def _get_module_info(usage_key, user, rewrite_static_links=True):
data
=
replace_static_urls
(
data
=
replace_static_urls
(
data
,
data
,
None
,
None
,
course_id
=
usage_key
.
course_key
course_id
=
module
.
location
.
course_key
)
)
# Note that children aren't being returned until we have a use case.
# Note that children aren't being returned until we have a use case.
return
{
return
{
'id'
:
unicode
(
usage_key
),
'id'
:
unicode
(
module
.
location
),
'data'
:
data
,
'data'
:
data
,
'metadata'
:
own_metadata
(
module
)
'metadata'
:
own_metadata
(
module
)
}
}
cms/djangoapps/contentstore/views/tests/test_course_index.py
View file @
3893a9ae
...
@@ -4,6 +4,7 @@ Unit tests for getting the list of courses and the course outline.
...
@@ -4,6 +4,7 @@ Unit tests for getting the list of courses and the course outline.
import
json
import
json
import
lxml
import
lxml
from
cms.urls
import
COURSE_KEY_PATTERN
from
contentstore.tests.utils
import
CourseTestCase
from
contentstore.tests.utils
import
CourseTestCase
from
contentstore.utils
import
reverse_course_url
from
contentstore.utils
import
reverse_course_url
from
xmodule.modulestore.tests.factories
import
CourseFactory
,
ItemFactory
from
xmodule.modulestore.tests.factories
import
CourseFactory
,
ItemFactory
...
@@ -38,7 +39,7 @@ class TestCourseIndex(CourseTestCase):
...
@@ -38,7 +39,7 @@ class TestCourseIndex(CourseTestCase):
for
link
in
course_link_eles
:
for
link
in
course_link_eles
:
self
.
assertRegexpMatches
(
self
.
assertRegexpMatches
(
link
.
get
(
"href"
),
link
.
get
(
"href"
),
'course/
slashes:{0}'
.
format
(
Locator
.
ALLOWED_ID_CHARS
)
'course/
{}'
.
format
(
COURSE_KEY_PATTERN
)
)
)
# now test that url
# now test that url
outline_response
=
authed_client
.
get
(
link
.
get
(
"href"
),
{},
HTTP_ACCEPT
=
'text/html'
)
outline_response
=
authed_client
.
get
(
link
.
get
(
"href"
),
{},
HTTP_ACCEPT
=
'text/html'
)
...
...
cms/djangoapps/contentstore/views/tests/test_item.py
View file @
3893a9ae
...
@@ -53,7 +53,10 @@ class ItemTest(CourseTestCase):
...
@@ -53,7 +53,10 @@ class ItemTest(CourseTestCase):
"""
"""
parsed
=
json
.
loads
(
response
.
content
)
parsed
=
json
.
loads
(
response
.
content
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
status_code
,
200
)
return
UsageKey
.
from_string
(
parsed
[
'locator'
])
key
=
UsageKey
.
from_string
(
parsed
[
'locator'
])
if
key
.
course_key
.
run
is
None
:
key
=
key
.
map_into_course
(
CourseKey
.
from_string
(
parsed
[
'courseKey'
]))
return
key
def
create_xblock
(
self
,
parent_usage_key
=
None
,
display_name
=
None
,
category
=
None
,
boilerplate
=
None
):
def
create_xblock
(
self
,
parent_usage_key
=
None
,
display_name
=
None
,
category
=
None
,
boilerplate
=
None
):
data
=
{
data
=
{
...
...
cms/urls.py
View file @
3893a9ae
...
@@ -5,6 +5,10 @@ from django.conf.urls import patterns, include, url
...
@@ -5,6 +5,10 @@ from django.conf.urls import patterns, include, url
from
ratelimitbackend
import
admin
from
ratelimitbackend
import
admin
admin
.
autodiscover
()
admin
.
autodiscover
()
COURSE_KEY_PATTERN
=
r'(?P<course_key_string>(?:[^/]+/[^/]+/[^/]+)|(?:[^/]+))'
USAGE_KEY_PATTERN
=
r'(?P<usage_key_string>(?:i4x://?[^/]+/[^/]+/[^/]+/[^@]+(?:@[^/]+)?)|(?:[^/]+))'
ASSET_KEY_PATTERN
=
r'(?P<asset_key_string>(?:/?c4x(:/)?/[^/]+/[^/]+/[^/]+/[^@]+(?:@[^/]+)?)|(?:[^/]+))'
urlpatterns
=
patterns
(
''
,
# nopep8
urlpatterns
=
patterns
(
''
,
# nopep8
url
(
r'^transcripts/upload$'
,
'contentstore.views.upload_transcripts'
,
name
=
'upload_transcripts'
),
url
(
r'^transcripts/upload$'
,
'contentstore.views.upload_transcripts'
,
name
=
'upload_transcripts'
),
...
@@ -66,30 +70,30 @@ urlpatterns += patterns(
...
@@ -66,30 +70,30 @@ urlpatterns += patterns(
url
(
r'^signin$'
,
'login_page'
,
name
=
'login'
),
url
(
r'^signin$'
,
'login_page'
,
name
=
'login'
),
url
(
r'^request_course_creator$'
,
'request_course_creator'
),
url
(
r'^request_course_creator$'
,
'request_course_creator'
),
url
(
r'^course_team/
(?P<course_key_string>[^/]+)/(?P<email>.+)?$'
,
'course_team_handler'
),
url
(
r'^course_team/
{}/(?P<email>.+)?$'
.
format
(
COURSE_KEY_PATTERN
)
,
'course_team_handler'
),
url
(
r'^course_info/
(?P<course_key_string>[^/]+)$'
,
'course_info_handler'
),
url
(
r'^course_info/
{}$'
.
format
(
COURSE_KEY_PATTERN
)
,
'course_info_handler'
),
url
(
url
(
r'^course_info_update/
(?P<course_key_string>[^/]+)/(?P<provided_id>\d+)?$'
,
r'^course_info_update/
{}/(?P<provided_id>\d+)?$'
.
format
(
COURSE_KEY_PATTERN
)
,
'course_info_update_handler'
'course_info_update_handler'
),
),
url
(
r'^course/
(?P<course_key_string>[^/]+)?$'
,
'course_handler'
,
name
=
'course_handler'
),
url
(
r'^course/
{}?$'
.
format
(
COURSE_KEY_PATTERN
)
,
'course_handler'
,
name
=
'course_handler'
),
url
(
r'^subsection/
(?P<usage_key_string>[^/]+)$'
,
'subsection_handler'
),
url
(
r'^subsection/
{}$'
.
format
(
USAGE_KEY_PATTERN
)
,
'subsection_handler'
),
url
(
r'^unit/
(?P<usage_key_string>[^/]+)$'
,
'unit_handler'
),
url
(
r'^unit/
{}$'
.
format
(
USAGE_KEY_PATTERN
)
,
'unit_handler'
),
url
(
r'^container/
(?P<usage_key_string>[^/]+)$'
,
'container_handler'
),
url
(
r'^container/
{}$'
.
format
(
USAGE_KEY_PATTERN
)
,
'container_handler'
),
url
(
r'^checklists/
(?P<course_key_string>[^/]+)/(?P<checklist_index>\d+)?$'
,
'checklists_handler'
),
url
(
r'^checklists/
{}/(?P<checklist_index>\d+)?$'
.
format
(
COURSE_KEY_PATTERN
)
,
'checklists_handler'
),
url
(
r'^orphan/
(?P<course_key_string>[^/]+)$'
,
'orphan_handler'
),
url
(
r'^orphan/
{}$'
.
format
(
COURSE_KEY_PATTERN
)
,
'orphan_handler'
),
url
(
r'^assets/
(?P<course_key_string>[^/]+)/(?P<asset_key_string>.+)?$'
,
'assets_handler'
),
url
(
r'^assets/
{}/{}?$'
.
format
(
COURSE_KEY_PATTERN
,
ASSET_KEY_PATTERN
)
,
'assets_handler'
),
url
(
r'^import/
(?P<course_key_string>[^/]+)$'
,
'import_handler'
),
url
(
r'^import/
{}$'
.
format
(
COURSE_KEY_PATTERN
)
,
'import_handler'
),
url
(
r'^import_status/
(?P<course_key_string>[^/]+)/(?P<filename>.+)$'
,
'import_status_handler'
),
url
(
r'^import_status/
{}/(?P<filename>.+)$'
.
format
(
COURSE_KEY_PATTERN
)
,
'import_status_handler'
),
url
(
r'^export/
(?P<course_key_string>[^/]+)$'
,
'export_handler'
),
url
(
r'^export/
{}$'
.
format
(
COURSE_KEY_PATTERN
)
,
'export_handler'
),
url
(
r'^xblock/
(?P<usage_key_string>[^/]+)/(?P<view_name>[^/]+)$'
,
'xblock_view_handler'
),
url
(
r'^xblock/
{}/(?P<view_name>[^/]+)$'
.
format
(
USAGE_KEY_PATTERN
)
,
'xblock_view_handler'
),
url
(
r'^xblock/
(?P<usage_key_string>[^/]+)?$'
,
'xblock_handler'
),
url
(
r'^xblock/
{}?$'
.
format
(
USAGE_KEY_PATTERN
)
,
'xblock_handler'
),
url
(
r'^tabs/
(?P<course_key_string>[^/]+)$'
,
'tabs_handler'
),
url
(
r'^tabs/
{}$'
.
format
(
COURSE_KEY_PATTERN
)
,
'tabs_handler'
),
url
(
r'^settings/details/
(?P<course_key_string>[^/]+)$'
,
'settings_handler'
),
url
(
r'^settings/details/
{}$'
.
format
(
COURSE_KEY_PATTERN
)
,
'settings_handler'
),
url
(
r'^settings/grading/
(?P<course_key_string>[^/]+)(/)?(?P<grader_index>\d+)?$'
,
'grading_handler'
),
url
(
r'^settings/grading/
{}(/)?(?P<grader_index>\d+)?$'
.
format
(
COURSE_KEY_PATTERN
)
,
'grading_handler'
),
url
(
r'^settings/advanced/
(?P<course_key_string>[^/]+)$'
,
'advanced_settings_handler'
),
url
(
r'^settings/advanced/
{}$'
.
format
(
COURSE_KEY_PATTERN
)
,
'advanced_settings_handler'
),
url
(
r'^textbooks/
(?P<course_key_string>[^/]+)$'
,
'textbooks_list_handler'
),
url
(
r'^textbooks/
{}$'
.
format
(
COURSE_KEY_PATTERN
)
,
'textbooks_list_handler'
),
url
(
r'^textbooks/
(?P<course_key_string>[^/]+)/(?P<textbook_id>\d[^/]*)$'
,
'textbooks_detail_handler'
),
url
(
r'^textbooks/
{}/(?P<textbook_id>\d[^/]*)$'
.
format
(
COURSE_KEY_PATTERN
)
,
'textbooks_detail_handler'
),
)
)
js_info_dict
=
{
js_info_dict
=
{
...
@@ -105,7 +109,7 @@ urlpatterns += patterns('',
...
@@ -105,7 +109,7 @@ urlpatterns += patterns('',
if
settings
.
FEATURES
.
get
(
'ENABLE_EXPORT_GIT'
):
if
settings
.
FEATURES
.
get
(
'ENABLE_EXPORT_GIT'
):
urlpatterns
+=
(
url
(
r'^export_git/
(?P<course_key_string>[^/]+)$'
,
urlpatterns
+=
(
url
(
r'^export_git/
{}$'
.
format
(
COURSE_KEY_PATTERN
)
,
'contentstore.views.export_git'
,
name
=
'export_git'
),)
'contentstore.views.export_git'
,
name
=
'export_git'
),)
if
settings
.
FEATURES
.
get
(
'ENABLE_SERVICE_STATUS'
):
if
settings
.
FEATURES
.
get
(
'ENABLE_SERVICE_STATUS'
):
...
...
common/lib/xmodule/xmodule/modulestore/mongo/base.py
View file @
3893a9ae
...
@@ -197,7 +197,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
...
@@ -197,7 +197,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
del
metadata
[
old_name
]
del
metadata
[
old_name
]
children
=
[
children
=
[
location
.
course_key
.
make_usage_key_from_deprecated_string
(
childloc
)
self
.
_convert_reference_to_key
(
childloc
)
for
childloc
in
definition
.
get
(
'children'
,
[])
for
childloc
in
definition
.
get
(
'children'
,
[])
]
]
data
=
definition
.
get
(
'data'
,
{})
data
=
definition
.
get
(
'data'
,
{})
...
@@ -254,6 +254,13 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
...
@@ -254,6 +254,13 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
error_msg
=
exc_info_to_str
(
sys
.
exc_info
())
error_msg
=
exc_info_to_str
(
sys
.
exc_info
())
)
)
def
_convert_reference_to_key
(
self
,
ref_string
):
"""
Convert a single serialized UsageKey string in a ReferenceField into a UsageKey.
"""
key
=
Location
.
from_deprecated_string
(
ref_string
)
return
key
.
replace
(
run
=
self
.
modulestore
.
_fill_in_run
(
key
.
course_key
)
.
run
)
def
_convert_reference_fields_to_keys
(
self
,
class_
,
course_key
,
jsonfields
):
def
_convert_reference_fields_to_keys
(
self
,
class_
,
course_key
,
jsonfields
):
"""
"""
Find all fields of type reference and convert the payload into UsageKeys
Find all fields of type reference and convert the payload into UsageKeys
...
@@ -267,15 +274,15 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
...
@@ -267,15 +274,15 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
if
field
is
None
:
if
field
is
None
:
continue
continue
elif
isinstance
(
field
,
Reference
):
elif
isinstance
(
field
,
Reference
):
jsonfields
[
field_name
]
=
course_key
.
make_usage_key_from_deprecated_string
(
value
)
jsonfields
[
field_name
]
=
self
.
_convert_reference_to_key
(
value
)
elif
isinstance
(
field
,
ReferenceList
):
elif
isinstance
(
field
,
ReferenceList
):
jsonfields
[
field_name
]
=
[
jsonfields
[
field_name
]
=
[
course_key
.
make_usage_key_from_deprecated_string
(
ele
)
for
ele
in
value
self
.
_convert_reference_to_key
(
ele
)
for
ele
in
value
]
]
elif
isinstance
(
field
,
ReferenceValueDict
):
elif
isinstance
(
field
,
ReferenceValueDict
):
for
key
,
subvalue
in
value
.
iteritems
():
for
key
,
subvalue
in
value
.
iteritems
():
assert
isinstance
(
subvalue
,
basestring
)
assert
isinstance
(
subvalue
,
basestring
)
value
[
key
]
=
course_key
.
make_usage_key_from_deprecated_string
(
subvalue
)
value
[
key
]
=
self
.
_convert_reference_to_key
(
subvalue
)
return
jsonfields
return
jsonfields
...
@@ -378,6 +385,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
...
@@ -378,6 +385,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
# performance optimization to prevent updating the meta-data inheritance tree during
# performance optimization to prevent updating the meta-data inheritance tree during
# bulk write operations
# bulk write operations
self
.
ignore_write_events_on_courses
=
set
()
self
.
ignore_write_events_on_courses
=
set
()
self
.
_course_run_cache
=
{}
def
begin_bulk_write_operation_on_course
(
self
,
course_id
):
def
begin_bulk_write_operation_on_course
(
self
,
course_id
):
"""
"""
...
@@ -394,6 +402,27 @@ class MongoModuleStore(ModuleStoreWriteBase):
...
@@ -394,6 +402,27 @@ class MongoModuleStore(ModuleStoreWriteBase):
self
.
ignore_write_events_on_courses
.
remove
(
course_id
)
self
.
ignore_write_events_on_courses
.
remove
(
course_id
)
self
.
refresh_cached_metadata_inheritance_tree
(
course_id
)
self
.
refresh_cached_metadata_inheritance_tree
(
course_id
)
def
_fill_in_run
(
self
,
course_key
):
if
course_key
.
run
is
not
None
:
return
course_key
cache_key
=
(
course_key
.
org
,
course_key
.
course
)
if
cache_key
not
in
self
.
_course_run_cache
:
matching_courses
=
list
(
self
.
collection
.
find
(
SON
([
(
'_id.tag'
,
'i4x'
),
(
'_id.org'
,
course_key
.
org
),
(
'_id.course'
,
course_key
.
course
),
(
'_id.category'
,
'course'
),
]))
.
limit
(
1
))
if
not
matching_courses
:
return
course_key
self
.
_course_run_cache
[
cache_key
]
=
matching_courses
[
0
][
'_id'
][
'name'
]
return
course_key
.
replace
(
run
=
self
.
_course_run_cache
[
cache_key
])
def
_compute_metadata_inheritance_tree
(
self
,
course_id
):
def
_compute_metadata_inheritance_tree
(
self
,
course_id
):
'''
'''
TODO (cdodge) This method can be deleted when the 'split module store' work has been completed
TODO (cdodge) This method can be deleted when the 'split module store' work has been completed
...
@@ -401,6 +430,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
...
@@ -401,6 +430,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
# get all collections in the course, this query should not return any leaf nodes
# get all collections in the course, this query should not return any leaf nodes
# note this is a bit ugly as when we add new categories of containers, we have to add it here
# note this is a bit ugly as when we add new categories of containers, we have to add it here
course_id
=
self
.
_fill_in_run
(
course_id
)
block_types_with_children
=
set
(
block_types_with_children
=
set
(
name
for
name
,
class_
in
XBlock
.
load_classes
()
if
getattr
(
class_
,
'has_children'
,
False
)
name
for
name
,
class_
in
XBlock
.
load_classes
()
if
getattr
(
class_
,
'has_children'
,
False
)
)
)
...
@@ -476,6 +506,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
...
@@ -476,6 +506,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
'''
'''
tree
=
{}
tree
=
{}
course_id
=
self
.
_fill_in_run
(
course_id
)
if
not
force_refresh
:
if
not
force_refresh
:
# see if we are first in the request cache (if present)
# see if we are first in the request cache (if present)
if
self
.
request_cache
is
not
None
and
course_id
in
self
.
request_cache
.
data
.
get
(
'metadata_inheritance'
,
{}):
if
self
.
request_cache
is
not
None
and
course_id
in
self
.
request_cache
.
data
.
get
(
'metadata_inheritance'
,
{}):
...
@@ -554,6 +585,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
...
@@ -554,6 +585,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
data
=
{}
data
=
{}
to_process
=
list
(
items
)
to_process
=
list
(
items
)
course_key
=
self
.
_fill_in_run
(
course_key
)
while
to_process
and
depth
is
None
or
depth
>=
0
:
while
to_process
and
depth
is
None
or
depth
>=
0
:
children
=
[]
children
=
[]
for
item
in
to_process
:
for
item
in
to_process
:
...
@@ -581,6 +613,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
...
@@ -581,6 +613,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
"""
"""
Load an XModuleDescriptor from item, using the children stored in data_cache
Load an XModuleDescriptor from item, using the children stored in data_cache
"""
"""
course_key
=
self
.
_fill_in_run
(
course_key
)
location
=
Location
.
_from_deprecated_son
(
item
[
'location'
],
course_key
.
run
)
location
=
Location
.
_from_deprecated_son
(
item
[
'location'
],
course_key
.
run
)
data_dir
=
getattr
(
item
,
'data_dir'
,
location
.
course
)
data_dir
=
getattr
(
item
,
'data_dir'
,
location
.
course
)
root
=
self
.
fs_root
/
data_dir
root
=
self
.
fs_root
/
data_dir
...
@@ -617,6 +650,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
...
@@ -617,6 +650,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
Load a list of xmodules from the data in items, with children cached up
Load a list of xmodules from the data in items, with children cached up
to specified depth
to specified depth
"""
"""
course_key
=
self
.
_fill_in_run
(
course_key
)
data_cache
=
self
.
_cache_children
(
course_key
,
items
,
depth
)
data_cache
=
self
.
_cache_children
(
course_key
,
items
,
depth
)
# if we are loading a course object, if we're not prefetching children (depth != 0) then don't
# if we are loading a course object, if we're not prefetching children (depth != 0) then don't
...
@@ -669,6 +703,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
...
@@ -669,6 +703,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
Get the course with the given courseid (org/course/run)
Get the course with the given courseid (org/course/run)
"""
"""
assert
(
isinstance
(
course_key
,
SlashSeparatedCourseKey
))
assert
(
isinstance
(
course_key
,
SlashSeparatedCourseKey
))
course_key
=
self
.
_fill_in_run
(
course_key
)
location
=
course_key
.
make_usage_key
(
'course'
,
course_key
.
run
)
location
=
course_key
.
make_usage_key
(
'course'
,
course_key
.
run
)
try
:
try
:
return
self
.
get_item
(
location
,
depth
=
depth
)
return
self
.
get_item
(
location
,
depth
=
depth
)
...
@@ -685,6 +720,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
...
@@ -685,6 +720,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
otherwise, do a case sensitive search
otherwise, do a case sensitive search
"""
"""
assert
(
isinstance
(
course_key
,
SlashSeparatedCourseKey
))
assert
(
isinstance
(
course_key
,
SlashSeparatedCourseKey
))
course_key
=
self
.
_fill_in_run
(
course_key
)
location
=
course_key
.
make_usage_key
(
'course'
,
course_key
.
run
)
location
=
course_key
.
make_usage_key
(
'course'
,
course_key
.
run
)
if
ignore_case
:
if
ignore_case
:
course_query
=
location
.
to_deprecated_son
(
'_id.'
)
course_query
=
location
.
to_deprecated_son
(
'_id.'
)
...
@@ -873,6 +909,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
...
@@ -873,6 +909,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
:param runtime: if you already have an xblock from the course, the xblock.runtime value
:param runtime: if you already have an xblock from the course, the xblock.runtime value
:param fields: a dictionary of field names and values for the new xmodule
:param fields: a dictionary of field names and values for the new xmodule
"""
"""
location
=
location
.
replace
(
run
=
self
.
_fill_in_run
(
location
.
course_key
)
.
run
)
# differs from split mongo in that I believe most of this logic should be above the persistence
# differs from split mongo in that I believe most of this logic should be above the persistence
# layer but added it here to enable quick conversion. I'll need to reconcile these.
# layer but added it here to enable quick conversion. I'll need to reconcile these.
if
metadata
is
None
:
if
metadata
is
None
:
...
@@ -1073,6 +1110,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
...
@@ -1073,6 +1110,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
"""
"""
Return an array of all of the locations (deprecated string format) for orphans in the course.
Return an array of all of the locations (deprecated string format) for orphans in the course.
"""
"""
course_key
=
self
.
_fill_in_run
(
course_key
)
detached_categories
=
[
name
for
name
,
__
in
XBlock
.
load_tagged_classes
(
"detached"
)]
detached_categories
=
[
name
for
name
,
__
in
XBlock
.
load_tagged_classes
(
"detached"
)]
query
=
self
.
_course_key_to_son
(
course_key
)
query
=
self
.
_course_key_to_son
(
course_key
)
query
[
'_id.category'
]
=
{
'$nin'
:
detached_categories
}
query
[
'_id.category'
]
=
{
'$nin'
:
detached_categories
}
...
...
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