* refactor: deprecates ModuleSystem.render_template in favor of the added MakoSystem render_template method. Related changes: * Adds the MakoService to the StudioEditModuleRuntime, PreviewModuleSystem, LmsModuleSystem, and XBlockRuntime * MakoService constructor takes a `namespace_prefix` string, so that the CMS PreviewModuleSystem can render to LMS templates, without needing the special render_from_lms helper method. * ModuleSystem.render_template becomes a read-only property, so the constructor calls and test module systems are updated accordingly. * Adds tests for the MakoService and module system shims. (cherry picked from commit457f959356) * refactor: use MakoService.render_template to remove deprecation warnings from block code. (cherry picked from commit8d62d337f5) * refactor: use MakoService.render_template to remove deprecation warnings from test code. (cherry picked from commit26b43465a4) * test: Adds a test to verify the bug introduced by the previous changes The AuthoringMixin is automatically added to all XBlocks (see settings.XBLOCK_MIXINS), and AuthoringMixin.visibility_view expects the "mako" service. This test verifies the bug by testing the PureXBlock, which does not require the "mako" service, and so fails when the visibility_view is rendered. * fix: AuthoringMixin needs mako service which fixes the visibility_view for XBlocks which don't explicitly require the mako service. Also removes the unneeded class property _services_requested from AuthoringMixin and StudioEditableBlock. This property is better provided by the XBlockMixin class.
82 lines
2.7 KiB
Python
82 lines
2.7 KiB
Python
"""
|
|
Code to handle mako templating for XModules and XBlocks.
|
|
"""
|
|
|
|
|
|
from web_fragments.fragment import Fragment
|
|
|
|
from .x_module import DescriptorSystem, XModuleDescriptor, shim_xmodule_js
|
|
|
|
|
|
class MakoDescriptorSystem(DescriptorSystem): # lint-amnesty, pylint: disable=abstract-method
|
|
"""
|
|
Descriptor system that renders mako templates.
|
|
"""
|
|
def __init__(self, render_template, **kwargs):
|
|
super().__init__(**kwargs)
|
|
|
|
self.render_template = render_template
|
|
|
|
# Add the MakoService to the descriptor system.
|
|
#
|
|
# This is not needed by most XBlocks, because they are initialized with a full runtime ModuleSystem that already
|
|
# has the MakoService.
|
|
# However, there are a few cases where the XBlock only has the descriptor system instead of the full module
|
|
# runtime. Specifically:
|
|
# * in the Instructor Dashboard bulk emails tab, when rendering the HtmlBlock for its WYSIWYG editor.
|
|
# * during testing, when using the ModuleSystemTestCase to fetch factory-created blocks.
|
|
from common.djangoapps.edxmako.services import MakoService
|
|
self._services['mako'] = MakoService()
|
|
|
|
|
|
class MakoTemplateBlockBase:
|
|
"""
|
|
XBlock intended as a mixin that uses a mako template
|
|
to specify the module html.
|
|
|
|
Expects the descriptor to have the `mako_template` attribute set
|
|
with the name of the template to render, and it will pass
|
|
the descriptor as the `module` parameter to that template
|
|
"""
|
|
# pylint: disable=no-member
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
if getattr(self.runtime, 'render_template', None) is None:
|
|
raise TypeError(
|
|
'{runtime} must have a render_template function'
|
|
' in order to use a MakoDescriptor'.format(
|
|
runtime=self.runtime,
|
|
)
|
|
)
|
|
|
|
def get_context(self):
|
|
"""
|
|
Return the context to render the mako template with
|
|
"""
|
|
return {
|
|
'module': self,
|
|
'editable_metadata_fields': self.editable_metadata_fields
|
|
}
|
|
|
|
def studio_view(self, context): # pylint: disable=unused-argument
|
|
"""
|
|
View used in Studio.
|
|
"""
|
|
# pylint: disable=no-member
|
|
fragment = Fragment(
|
|
self.system.render_template(self.mako_template, self.get_context())
|
|
)
|
|
shim_xmodule_js(fragment, self.js_module_name)
|
|
return fragment
|
|
|
|
|
|
class MakoModuleDescriptor(MakoTemplateBlockBase, XModuleDescriptor): # pylint: disable=abstract-method
|
|
"""
|
|
Mixin to use for XModule descriptors.
|
|
"""
|
|
resources_dir = None
|
|
|
|
def get_html(self):
|
|
return self.studio_view(None).content
|