-
Notifications
You must be signed in to change notification settings - Fork 4.3k
preview_handler changes to support Locators #2434
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,7 +11,8 @@ | |
| from xmodule_modifiers import replace_static_urls, wrap_xblock | ||
| from xmodule.error_module import ErrorDescriptor | ||
| from xmodule.exceptions import NotFoundError, ProcessingError | ||
| from xmodule.modulestore.django import modulestore | ||
| from xmodule.modulestore.django import modulestore, loc_mapper | ||
| from xmodule.modulestore.locator import Locator | ||
| from xmodule.x_module import ModuleSystem | ||
| from xblock.runtime import KvsFieldData | ||
| from xblock.django.request import webob_to_django_response, django_to_webob_request | ||
|
|
@@ -44,7 +45,8 @@ def preview_handler(request, usage_id, handler, suffix=''): | |
| handler: The handler to execute | ||
| suffix: The remainder of the url to be passed to the handler | ||
| """ | ||
|
|
||
| # Note: usage_id is currently the string form of a Location, but in the | ||
| # future it will be the string representation of a Locator. | ||
| location = unquote_slashes(usage_id) | ||
|
|
||
| descriptor = modulestore().get_item(location) | ||
|
|
@@ -95,7 +97,11 @@ def _preview_module_system(request, descriptor): | |
| descriptor: An XModuleDescriptor | ||
| """ | ||
|
|
||
| course_id = get_course_for_item(descriptor.location).location.course_id | ||
| if isinstance(descriptor.location, Locator): | ||
| course_location = loc_mapper().translate_locator_to_location(descriptor.location, get_course=True) | ||
| course_id = course_location.course_id | ||
| else: | ||
| course_id = get_course_for_item(descriptor.location).location.course_id | ||
|
|
||
| return PreviewModuleSystem( | ||
| static_url=settings.STATIC_URL, | ||
|
|
@@ -115,17 +121,15 @@ def _preview_module_system(request, descriptor): | |
| # Set up functions to modify the fragment produced by student_view | ||
| wrappers=( | ||
| # This wrapper wraps the module in the template specified above | ||
| partial(wrap_xblock, 'PreviewRuntime', display_name_only=descriptor.location.category == 'static_tab'), | ||
| partial(wrap_xblock, 'PreviewRuntime', display_name_only=descriptor.category == 'static_tab'), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you sure getting rid of
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. None is passed for data_directory in the call above. I looked at the code that is being called, and it seems that data_directory is only used for XML modulestore (which Studio doesn't use). The code is in /edx-platform/common/djangoapps/static_replace/init.py I couldn't think of any reason why the arguments should be different in the 2 places. Do you know of a reason why they should differ?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair enough. I think that should be fine in this code. Another good reason that we should clean up the api for the ContentStore and static replacement, so that we don't have to have all of these special cases depending on whether we're in an XML world or a mongo one. |
||
|
|
||
| # This wrapper replaces urls in the output that start with /static | ||
| # with the correct course-specific url for the static content | ||
| partial( | ||
| replace_static_urls, | ||
| getattr(descriptor, 'data_dir', descriptor.location.course), | ||
| course_id=descriptor.location.org + '/' + descriptor.location.course + '/BOGUS_RUN_REPLACE_WHEN_AVAILABLE', | ||
| ), | ||
| partial(replace_static_urls, None, course_id=course_id), | ||
| ), | ||
| error_descriptor_class=ErrorDescriptor, | ||
| # get_user_role accepts a location or a CourseLocator. | ||
| # If descriptor.location is a CourseLocator, course_id is unused. | ||
| get_user_role=lambda: get_user_role(request.user, descriptor.location, course_id), | ||
| ) | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| """ | ||
| Tests for contentstore.views.preview.py | ||
| """ | ||
| from django.test import TestCase | ||
| from django.test.client import RequestFactory | ||
|
|
||
| from student.tests.factories import UserFactory | ||
|
|
||
| from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory | ||
| from xmodule.modulestore.django import loc_mapper | ||
|
|
||
| from contentstore.views.preview import get_preview_fragment | ||
|
|
||
|
|
||
| class GetPreviewHtmlTestCase(TestCase): | ||
| """ | ||
| Tests for get_preview_html. | ||
|
|
||
| Note that there are other existing test cases in test_contentstore that indirectly execute | ||
| get_preview_html via the xblock RESTful API. | ||
| """ | ||
|
|
||
| def test_preview_handler_locator(self): | ||
| """ | ||
| Test for calling get_preview_html when descriptor.location is a Locator. | ||
| """ | ||
| course = CourseFactory.create() | ||
| html = ItemFactory.create( | ||
| parent_location=course.location, | ||
| category="html", | ||
| data={'data': "<html>foobar</html>"} | ||
| ) | ||
|
|
||
| locator = loc_mapper().translate_location( | ||
| course.location.course_id, html.location, True, True | ||
| ) | ||
|
|
||
| # Change the stored location to a locator. | ||
| html.location = locator | ||
| html.save() | ||
|
|
||
| request = RequestFactory().get('/dummy-url') | ||
| request.user = UserFactory() | ||
| request.session = {} | ||
|
|
||
| # Must call get_preview_fragment directly, as going through xblock RESTful API will attempt | ||
| # to use item.location as a Location. | ||
| html = get_preview_fragment(request, html).content | ||
| # Verify student view html is returned, and there are no old locations in it. | ||
| self.assertRegexpMatches( | ||
| html, | ||
| 'data-usage-id="MITx.999.Robot_Super_Course;_branch;_published;_block;_html_[0-9]*"' | ||
| ) | ||
| self.assertRegexpMatches(html, '<html>foobar</html>') | ||
| self.assertNotRegexpMatches(html, 'i4x') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to go away when the modulestore handles locator/location translation, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, though we will have to get the course_id.