From 5406b9bb40cb644473f4acdbc79153c14832cbeb Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Tue, 10 Jul 2012 12:54:47 -0400 Subject: [PATCH] Make /static/ urls work in the courseware --- common/djangoapps/static_replace.py | 30 ++++++++++------- common/lib/xmodule/xmodule/capa_module.py | 3 +- common/lib/xmodule/xmodule/modulestore/xml.py | 4 ++- common/lib/xmodule/xmodule/x_module.py | 8 ++++- lms/djangoapps/courseware/module_render.py | 33 +++++++++++++++++-- lms/envs/common.py | 15 ++++----- lms/templates/main.html | 4 +++ lms/templates/problem.html | 2 +- 8 files changed, 73 insertions(+), 26 deletions(-) diff --git a/common/djangoapps/static_replace.py b/common/djangoapps/static_replace.py index c6c6dd0bc2..cc698a5714 100644 --- a/common/djangoapps/static_replace.py +++ b/common/djangoapps/static_replace.py @@ -1,19 +1,25 @@ from staticfiles.storage import staticfiles_storage import re -PREFIX = '/static/' -STATIC_PATTERN = re.compile(r""" -(?P['"]) # the opening quotes -{prefix} # the prefix -(?P.*?) # everything else in the url -(?P=quote) # the first matching closing quote -""".format(prefix=PREFIX), re.VERBOSE) -PREFIX_LEN = len(PREFIX) -def replace(static_url): +def replace(static_url, prefix=None): + if prefix is None: + prefix = '' + else: + prefix = prefix + '/' + quote = static_url.group('quote') - url = staticfiles_storage.url(static_url.group('rest')) + url = staticfiles_storage.url(prefix + static_url.group('rest')) return "".join([quote, url, quote]) -def replace_urls(text): - return STATIC_PATTERN.sub(replace, text) + +def replace_urls(text, staticfiles_prefix=None, replace_prefix='/static/'): + def replace_url(static_url): + return replace(static_url, staticfiles_prefix) + + return re.sub(r""" + (?P\\?['"]) # the opening quotes + {prefix} # the prefix + (?P.*?) # everything else in the url + (?P=quote) # the first matching closing quote + """.format(prefix=replace_prefix), replace_url, text, flags=re.VERBOSE) diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index 3cafcbde3d..692b26f00c 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -15,6 +15,7 @@ from xmodule.raw_module import RawDescriptor from progress import Progress from capa.capa_problem import LoncapaProblem from capa.responsetypes import StudentInputError +from static_replace import replace_urls log = logging.getLogger("mitx.courseware") @@ -258,7 +259,7 @@ class CapaModule(XModule): html = '
'.format( id=self.location.html_id(), ajax_url=self.system.ajax_url) + html + "
" - return html + return replace_urls(html, self.metadata['data_dir']) def handle_ajax(self, dispatch, get): ''' diff --git a/common/lib/xmodule/xmodule/modulestore/xml.py b/common/lib/xmodule/xmodule/modulestore/xml.py index 76056bc069..dc178b7c9f 100644 --- a/common/lib/xmodule/xmodule/modulestore/xml.py +++ b/common/lib/xmodule/xmodule/modulestore/xml.py @@ -115,7 +115,9 @@ class XMLModuleStore(ModuleStore): MakoDescriptorSystem.__init__(self, **system_kwargs) XMLParsingSystem.__init__(self, **system_kwargs) - return ImportSystem(self).process_xml(etree.tostring(course_data)) + course_descriptor = ImportSystem(self).process_xml(etree.tostring(course_data)) + course_descriptor.metadata['data_dir'] = course_dir + return course_descriptor def get_item(self, location): """ diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index 52352c7d2b..c0222cdab3 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -211,7 +211,13 @@ class XModuleDescriptor(Plugin): js_module = None # A list of metadata that this module can inherit from its parent module - inheritable_metadata = ('graded', 'due', 'graceperiod', 'showanswer', 'rerandomize') + inheritable_metadata = ( + 'graded', 'due', 'graceperiod', 'showanswer', 'rerandomize', + + # This is used by the XMLModuleStore to provide for locations for static files, + # and will need to be removed when that code is removed + 'data_dir' + ) # A list of descriptor attributes that must be equal for the discriptors to be # equal diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index b9110782c5..7e452692a4 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -1,15 +1,15 @@ import json import logging -import os from django.conf import settings from django.http import Http404 from django.http import HttpResponse -from lxml import etree +from functools import wraps from xmodule.modulestore.django import modulestore from mitxmako.shortcuts import render_to_string from models import StudentModule, StudentModuleCache +from static_replace import replace_urls log = logging.getLogger("mitx.courseware") @@ -222,6 +222,12 @@ def get_module(user, request, location, student_module_cache, position=None): module = descriptor.xmodule_constructor(system)(instance_state, shared_state) + # TODO (cpennington): When modules are shared between courses, the static + # prefix is going to have to be specific to the module, not the directory + # that the xml was loaded from + prefix = module.metadata['data_dir'] + module = replace_static_urls(module, prefix) + if settings.MITX_FEATURES.get('DISPLAY_HISTOGRAMS_TO_STAFF') and user.is_staff: module = add_histogram(module) @@ -251,9 +257,32 @@ def get_module(user, request, location, student_module_cache, position=None): return (module, instance_module, shared_module, descriptor.category) +def replace_static_urls(module, prefix): + """ + Updates the supplied module with a new get_html function that wraps + the old get_html function and substitutes urls of the form /static/... + with urls that are /static//... + """ + original_get_html = module.get_html + + @wraps(original_get_html) + def get_html(): + return replace_urls(original_get_html(), staticfiles_prefix=prefix) + + module.get_html = get_html + return module + + def add_histogram(module): + """ + Updates the supplied module with a new get_html function that wraps + the output of the old get_html function with additional information + for admin users only, including a histogram of student answers and the + definition of the xmodule + """ original_get_html = module.get_html + @wraps(original_get_html) def get_html(): module_id = module.id histogram = grade_histogram(module_id) diff --git a/lms/envs/common.py b/lms/envs/common.py index 5cf3848d13..d4fff92d23 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -19,6 +19,7 @@ Longer TODO: multiple sites, but we do need a way to map their data assets. """ import sys +import os import tempfile import glob2 @@ -167,19 +168,17 @@ MANAGERS = ADMINS # Static content STATIC_URL = '/static/' ADMIN_MEDIA_PREFIX = '/static/admin/' -STATIC_ROOT = ENV_ROOT / "staticfiles" +STATIC_ROOT = ENV_ROOT / "staticfiles" -# FIXME: We should iterate through the courses we have, adding the static -# contents for each of them. (Right now we just use symlinks.) STATICFILES_DIRS = [ PROJECT_ROOT / "static", ASKBOT_ROOT / "askbot" / "skins", - ("circuits", DATA_DIR / "images"), - ("handouts", DATA_DIR / "handouts"), - ("subs", DATA_DIR / "subs"), -# This is how you would use the textbook images locally -# ("book", ENV_ROOT / "book_images") +] + [ + # TODO (cpennington): When courses are stored in a database, this + # should no longer be added to STATICFILES + (course_dir, DATA_DIR / course_dir) + for course_dir in os.listdir(DATA_DIR) ] # Locale/Internationalization diff --git a/lms/templates/main.html b/lms/templates/main.html index 8ce728fe3c..674caf6298 100644 --- a/lms/templates/main.html +++ b/lms/templates/main.html @@ -21,6 +21,10 @@ + ## TODO (cpennington): Remove this when we have a good way for modules to specify js to load on the page + ## and in the wiki + + % if settings.MITX_FEATURES['USE_DJANGO_PIPELINE']: <%static:js group='application'/> % endif diff --git a/lms/templates/problem.html b/lms/templates/problem.html index 36fcb1bc66..d051740710 100644 --- a/lms/templates/problem.html +++ b/lms/templates/problem.html @@ -13,7 +13,7 @@
- ${ static.replace_urls(problem['html']) } + ${ problem['html'] }