diff --git a/cms/djangoapps/contentstore/tests/test_item.py b/cms/djangoapps/contentstore/tests/test_item.py index 238660f510..376f8ff82e 100644 --- a/cms/djangoapps/contentstore/tests/test_item.py +++ b/cms/djangoapps/contentstore/tests/test_item.py @@ -538,6 +538,41 @@ class TestEditItem(ItemTest): draft = self.get_item_from_modulestore(self.problem_locator, True) self.assertEqual(draft.due, datetime(2077, 10, 10, 4, 0, tzinfo=UTC)) + def test_published_and_draft_contents_with_update(self): + """ Create a draft and publish it then modify the draft and check that published content is not modified """ + + # Make problem public. + resp = self.client.ajax_post( + self.problem_update_url, + data={'publish': 'make_public'} + ) + self.assertIsNotNone(self.get_item_from_modulestore(self.problem_locator, False)) + + # Now make a draft + resp = self.client.ajax_post( + self.problem_update_url, + data={ + 'id': self.problem_locator, + 'metadata': {}, + 'data': "
Problem content draft.
", + 'publish': 'create_draft' + } + ) + + # Both published and draft content should be different + published = self.get_item_from_modulestore(self.problem_locator, False) + draft = self.get_item_from_modulestore(self.problem_locator, True) + self.assertNotEqual(draft.data, published.data) + + # Get problem by 'xblock_handler' + resp = self.client.get('/xblock/' + self.problem_locator, HTTP_ACCEPT='application/x-fragment+json') + self.assertEqual(resp.status_code, 200) + + # Both published and draft content should still be different + published = self.get_item_from_modulestore(self.problem_locator, False) + draft = self.get_item_from_modulestore(self.problem_locator, True) + self.assertNotEqual(draft.data, published.data) + @ddt.ddt class TestComponentHandler(TestCase): diff --git a/cms/djangoapps/contentstore/views/item.py b/cms/djangoapps/contentstore/views/item.py index 8d80d9e0bb..dfb5fd5704 100644 --- a/cms/djangoapps/contentstore/views/item.py +++ b/cms/djangoapps/contentstore/views/item.py @@ -112,7 +112,8 @@ def xblock_handler(request, tag=None, package_id=None, branch=None, version_guid accept_header = request.META.get('HTTP_ACCEPT', 'application/json') if 'application/x-fragment+json' in accept_header: - component = modulestore().get_item(old_location) + store = get_modulestore(old_location) + component = store.get_item(old_location) # Wrap the generated fragment in the xmodule_editor div so that the javascript # can bind to it correctly @@ -127,7 +128,7 @@ def xblock_handler(request, tag=None, package_id=None, branch=None, version_guid log.debug("Unable to render studio_view for %r", component, exc_info=True) editor_fragment = Fragment(render_to_string('html_error.html', {'message': str(exc)})) - modulestore().save_xmodule(component) + store.save_xmodule(component) preview_fragment = get_preview_fragment(request, component) diff --git a/common/lib/xmodule/xmodule/modulestore/mongo/draft.py b/common/lib/xmodule/xmodule/modulestore/mongo/draft.py index f7a0250155..7ebc7a5a05 100644 --- a/common/lib/xmodule/xmodule/modulestore/mongo/draft.py +++ b/common/lib/xmodule/xmodule/modulestore/mongo/draft.py @@ -108,6 +108,20 @@ class DraftModuleStore(MongoModuleStore): raise InvalidVersionError(location) return super(DraftModuleStore, self).create_xmodule(draft_loc, definition_data, metadata, system) + def save_xmodule(self, xmodule): + """ + Save the given xmodule (will either create or update based on whether id already exists). + Pulls out the data definition v metadata v children locally but saves it all. + + :param xmodule: + """ + orig_location = xmodule.location + + xmodule.location = as_draft(orig_location) + try: + super(DraftModuleStore, self).save_xmodule(xmodule) + finally: + xmodule.location = orig_location def get_items(self, location, course_id=None, depth=0): """