Instead, we use XModule field default values when creating an empty XModule. Driven by this use case, we also allow for XModules to be created in memory without being persisted to the database at all. This necessitates a change to the Modulestore api, replacing clone_item with create_draft and save_xmodule.
81 lines
3.3 KiB
Python
81 lines
3.3 KiB
Python
from static_replace import replace_static_urls
|
|
from xmodule.modulestore.exceptions import ItemNotFoundError
|
|
from xmodule.modulestore import Location
|
|
|
|
|
|
def get_module_info(store, location, rewrite_static_links=False):
|
|
try:
|
|
module = store.get_item(location)
|
|
except ItemNotFoundError:
|
|
# create a new one
|
|
store.create_and_save_xmodule(location)
|
|
module = store.get_item(location)
|
|
|
|
data = module.data
|
|
if rewrite_static_links:
|
|
data = replace_static_urls(
|
|
module.data,
|
|
None,
|
|
course_namespace=Location([
|
|
module.location.tag,
|
|
module.location.org,
|
|
module.location.course,
|
|
None,
|
|
None
|
|
])
|
|
)
|
|
|
|
return {
|
|
'id': module.location.url(),
|
|
'data': data,
|
|
# TODO (cpennington): This really shouldn't have to do this much reaching in to get the metadata
|
|
# what's the intent here? all metadata incl inherited & namespaced?
|
|
'metadata': module.xblock_kvs._metadata
|
|
}
|
|
|
|
|
|
def set_module_info(store, location, post_data):
|
|
module = None
|
|
try:
|
|
module = store.get_item(location)
|
|
except ItemNotFoundError:
|
|
# new module at this location: almost always used for the course about pages; thus, no parent. (there
|
|
# are quite a handful of about page types available for a course and only the overview is pre-created)
|
|
store.create_and_save_xmodule(location)
|
|
module = store.get_item(location)
|
|
|
|
if post_data.get('data') is not None:
|
|
data = post_data['data']
|
|
store.update_item(location, data)
|
|
|
|
# cdodge: note calling request.POST.get('children') will return None if children is an empty array
|
|
# so it lead to a bug whereby the last component to be deleted in the UI was not actually
|
|
# deleting the children object from the children collection
|
|
if 'children' in post_data and post_data['children'] is not None:
|
|
children = post_data['children']
|
|
store.update_children(location, children)
|
|
|
|
# cdodge: also commit any metadata which might have been passed along in the
|
|
# POST from the client, if it is there
|
|
# NOTE, that the postback is not the complete metadata, as there's system metadata which is
|
|
# not presented to the end-user for editing. So let's fetch the original and
|
|
# 'apply' the submitted metadata, so we don't end up deleting system metadata
|
|
if post_data.get('metadata') is not None:
|
|
posted_metadata = post_data['metadata']
|
|
|
|
# update existing metadata with submitted metadata (which can be partial)
|
|
# IMPORTANT NOTE: if the client passed pack 'null' (None) for a piece of metadata that means 'remove it'
|
|
for metadata_key, value in posted_metadata.items():
|
|
|
|
if posted_metadata[metadata_key] is None:
|
|
# remove both from passed in collection as well as the collection read in from the modulestore
|
|
if metadata_key in module._model_data:
|
|
del module._model_data[metadata_key]
|
|
del posted_metadata[metadata_key]
|
|
else:
|
|
module._model_data[metadata_key] = value
|
|
|
|
# commit to datastore
|
|
# TODO (cpennington): This really shouldn't have to do this much reaching in to get the metadata
|
|
store.update_metadata(location, module.xblock_kvs._metadata)
|