Split out code to replace /static urls in get_html into a separate module so that it can be used in CMS previews
This commit is contained in:
@@ -14,6 +14,7 @@ from static_replace import replace_urls
|
||||
|
||||
from mitxmako.shortcuts import render_to_response, render_to_string
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule_modifiers import replace_static_urls
|
||||
|
||||
|
||||
# ==== Public views ==================================================
|
||||
@@ -167,8 +168,21 @@ def get_sample_module(location):
|
||||
"""
|
||||
descriptor = modulestore().get_item(location)
|
||||
instance_state, shared_state = descriptor.get_sample_state()[0]
|
||||
return load_sample_module(descriptor, instance_state, shared_state)
|
||||
|
||||
|
||||
def load_sample_module(descriptor, instance_state, shared_state):
|
||||
"""
|
||||
Return a sample XModule instantiated from the supplied descriptor, instance_state, and shared_state
|
||||
|
||||
descriptor: An XModuleDescriptor
|
||||
instance_state: An instance state string
|
||||
shared_state: A shared state string
|
||||
"""
|
||||
system = sample_module_system(descriptor)
|
||||
module = descriptor.xmodule_constructor(system)(instance_state, shared_state)
|
||||
module.get_html = replace_static_urls(module.get_html, module.metadata['data_dir'])
|
||||
|
||||
return module
|
||||
|
||||
|
||||
@@ -180,9 +194,8 @@ def get_module_previews(descriptor):
|
||||
descriptor: An XModuleDescriptor
|
||||
"""
|
||||
preview_html = []
|
||||
system = sample_module_system(descriptor)
|
||||
for instance_state, shared_state in descriptor.get_sample_state():
|
||||
module = descriptor.xmodule_constructor(system)(instance_state, shared_state)
|
||||
module = load_sample_module(descriptor, instance_state, shared_state)
|
||||
preview_html.append(module.get_html())
|
||||
return preview_html
|
||||
|
||||
|
||||
@@ -155,6 +155,13 @@ STATICFILES_DIRS = [
|
||||
# This is how you would use the textbook images locally
|
||||
# ("book", ENV_ROOT / "book_images")
|
||||
]
|
||||
if os.path.isdir(GITHUB_REPO_ROOT):
|
||||
STATICFILES_DIRS += [
|
||||
# TODO (cpennington): When courses aren't loaded from github, remove this
|
||||
(course_dir, GITHUB_REPO_ROOT / course_dir)
|
||||
for course_dir in os.listdir(GITHUB_REPO_ROOT)
|
||||
if os.path.isdir(GITHUB_REPO_ROOT / course_dir)
|
||||
]
|
||||
|
||||
# Locale/Internationalization
|
||||
TIME_ZONE = 'America/New_York' # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
||||
|
||||
79
common/djangoapps/xmodule_modifiers.py
Normal file
79
common/djangoapps/xmodule_modifiers.py
Normal file
@@ -0,0 +1,79 @@
|
||||
import json
|
||||
from django.conf import settings
|
||||
from functools import wraps
|
||||
from static_replace import replace_urls
|
||||
from mitxmako.shortcuts import render_to_string
|
||||
|
||||
|
||||
def replace_static_urls(original, 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/<prefix>/...
|
||||
"""
|
||||
|
||||
@wraps(original)
|
||||
def get_html():
|
||||
return replace_urls(original(), staticfiles_prefix=prefix)
|
||||
return get_html
|
||||
|
||||
|
||||
def grade_histogram(module_id):
|
||||
''' Print out a histogram of grades on a given problem.
|
||||
Part of staff member debug info.
|
||||
'''
|
||||
from django.db import connection
|
||||
cursor = connection.cursor()
|
||||
|
||||
q = """SELECT courseware_studentmodule.grade,
|
||||
COUNT(courseware_studentmodule.student_id)
|
||||
FROM courseware_studentmodule
|
||||
WHERE courseware_studentmodule.module_id=%s
|
||||
GROUP BY courseware_studentmodule.grade"""
|
||||
# Passing module_id this way prevents sql-injection.
|
||||
cursor.execute(q, [module_id])
|
||||
|
||||
grades = list(cursor.fetchall())
|
||||
grades.sort(key=lambda x: x[0]) # Add ORDER BY to sql query?
|
||||
if len(grades) == 1 and grades[0][0] is None:
|
||||
return []
|
||||
return grades
|
||||
|
||||
|
||||
def add_histogram(original, 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
|
||||
"""
|
||||
@wraps(original)
|
||||
def get_html():
|
||||
module_id = module.id
|
||||
histogram = grade_histogram(module_id)
|
||||
render_histogram = len(histogram) > 0
|
||||
|
||||
# TODO: fixme - no filename in module.xml in general (this code block for edx4edx)
|
||||
# the following if block is for summer 2012 edX course development; it will change when the CMS comes online
|
||||
if settings.MITX_FEATURES.get('DISPLAY_EDIT_LINK') and settings.DEBUG and module_xml.get('filename') is not None:
|
||||
coursename = multicourse_settings.get_coursename_from_request(request)
|
||||
github_url = multicourse_settings.get_course_github_url(coursename)
|
||||
fn = module_xml.get('filename')
|
||||
if module_xml.tag=='problem': fn = 'problems/' + fn # grrr
|
||||
edit_link = (github_url + '/tree/master/' + fn) if github_url is not None else None
|
||||
if module_xml.tag=='problem': edit_link += '.xml' # grrr
|
||||
else:
|
||||
edit_link = False
|
||||
|
||||
# Cast module.definition and module.metadata to dicts so that json can dump them
|
||||
# even though they are lazily loaded
|
||||
staff_context = {'definition': json.dumps(dict(module.definition), indent=4),
|
||||
'metadata': json.dumps(dict(module.metadata), indent=4),
|
||||
'element_id': module.location.html_id(),
|
||||
'edit_link': edit_link,
|
||||
'histogram': json.dumps(histogram),
|
||||
'render_histogram': render_histogram,
|
||||
'module_content': original()}
|
||||
return render_to_string("staff_problem_info.html", staff_context)
|
||||
|
||||
return get_html
|
||||
@@ -5,7 +5,6 @@ from django.conf import settings
|
||||
from django.http import Http404
|
||||
from django.http import HttpResponse
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from functools import wraps
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from xmodule.modulestore.django import modulestore
|
||||
@@ -14,6 +13,7 @@ from models import StudentModule, StudentModuleCache
|
||||
from static_replace import replace_urls
|
||||
from xmodule.exceptions import NotFoundError
|
||||
from xmodule.x_module import ModuleSystem
|
||||
from xmodule_modifiers import replace_static_urls, add_histogram
|
||||
|
||||
log = logging.getLogger("mitx.courseware")
|
||||
|
||||
@@ -30,28 +30,6 @@ def make_track_function(request):
|
||||
return f
|
||||
|
||||
|
||||
def grade_histogram(module_id):
|
||||
''' Print out a histogram of grades on a given problem.
|
||||
Part of staff member debug info.
|
||||
'''
|
||||
from django.db import connection
|
||||
cursor = connection.cursor()
|
||||
|
||||
q = """SELECT courseware_studentmodule.grade,
|
||||
COUNT(courseware_studentmodule.student_id)
|
||||
FROM courseware_studentmodule
|
||||
WHERE courseware_studentmodule.module_id=%s
|
||||
GROUP BY courseware_studentmodule.grade"""
|
||||
# Passing module_id this way prevents sql-injection.
|
||||
cursor.execute(q, [module_id])
|
||||
|
||||
grades = list(cursor.fetchall())
|
||||
grades.sort(key=lambda x: x[0]) # Add ORDER BY to sql query?
|
||||
if len(grades) == 1 and grades[0][0] is None:
|
||||
return []
|
||||
return grades
|
||||
|
||||
|
||||
def toc_for_course(user, request, course, active_chapter, active_section):
|
||||
'''
|
||||
Create a table of contents from the module store
|
||||
@@ -180,11 +158,10 @@ def get_module(user, request, location, student_module_cache, position=None):
|
||||
|
||||
module = descriptor.xmodule_constructor(system)(instance_state, shared_state)
|
||||
|
||||
replace_prefix = module.metadata['data_dir']
|
||||
module = replace_static_urls(module, replace_prefix)
|
||||
module.get_html = replace_static_urls(module.get_html, module.metadata['data_dir'])
|
||||
|
||||
if settings.MITX_FEATURES.get('DISPLAY_HISTOGRAMS_TO_STAFF') and user.is_staff:
|
||||
module = add_histogram(module)
|
||||
module.get_html = add_histogram(module.get_html)
|
||||
|
||||
# If StudentModule for this instance wasn't already in the database,
|
||||
# and this isn't a guest user, create it.
|
||||
@@ -212,64 +189,6 @@ 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/<prefix>/...
|
||||
"""
|
||||
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)
|
||||
render_histogram = len(histogram) > 0
|
||||
|
||||
# TODO: fixme - no filename in module.xml in general (this code block for edx4edx)
|
||||
# the following if block is for summer 2012 edX course development; it will change when the CMS comes online
|
||||
if settings.MITX_FEATURES.get('DISPLAY_EDIT_LINK') and settings.DEBUG and module_xml.get('filename') is not None:
|
||||
coursename = multicourse_settings.get_coursename_from_request(request)
|
||||
github_url = multicourse_settings.get_course_github_url(coursename)
|
||||
fn = module_xml.get('filename')
|
||||
if module_xml.tag == 'problem': fn = 'problems/' + fn # grrr
|
||||
edit_link = (github_url + '/tree/master/' + fn) if github_url is not None else None
|
||||
if module_xml.tag == 'problem': edit_link += '.xml' # grrr
|
||||
else:
|
||||
edit_link = False
|
||||
|
||||
# Cast module.definition and module.metadata to dicts so that json can dump them
|
||||
# even though they are lazily loaded
|
||||
staff_context = {'definition': json.dumps(dict(module.definition), indent=4),
|
||||
'metadata': json.dumps(dict(module.metadata), indent=4),
|
||||
'element_id': module.location.html_id(),
|
||||
'edit_link': edit_link,
|
||||
'histogram': json.dumps(histogram),
|
||||
'render_histogram': render_histogram,
|
||||
'module_content': original_get_html()}
|
||||
return render_to_string("staff_problem_info.html", staff_context)
|
||||
|
||||
module.get_html = get_html
|
||||
return module
|
||||
|
||||
|
||||
# TODO: TEMPORARY BYPASS OF AUTH!
|
||||
@csrf_exempt
|
||||
def xqueue_callback(request, userid, id, dispatch):
|
||||
|
||||
Reference in New Issue
Block a user