diff --git a/cms/djangoapps/models/settings/course_grading.py b/cms/djangoapps/models/settings/course_grading.py
index aeb808ec38..ca3a72c3db 100644
--- a/cms/djangoapps/models/settings/course_grading.py
+++ b/cms/djangoapps/models/settings/course_grading.py
@@ -135,7 +135,7 @@ class CourseGradingModel(object):
descriptor = get_modulestore(course_location).get_item(course_location)
descriptor.grade_cutoffs = cutoffs
- get_modulestore(course_location).update_item(course_location, descriptor.definition['data'])
+ get_modulestore(course_location).update_item(course_location, descriptor._model_data._kvs._data)
return cutoffs
@@ -203,8 +203,8 @@ class CourseGradingModel(object):
course_location = Location(course_location)
descriptor = get_modulestore(course_location).get_item(course_location)
- if 'graceperiod' in descriptor.metadata: del descriptor.metadata['graceperiod']
- get_modulestore(course_location).update_metadata(course_location, descriptor._model_data._kvs._data)
+ del descriptor.lms.graceperiod
+ get_modulestore(course_location).update_metadata(course_location, descriptor._model_data._kvs._metadata)
@staticmethod
def get_section_grader_type(location):
@@ -213,7 +213,7 @@ class CourseGradingModel(object):
descriptor = get_modulestore(location).get_item(location)
return {
- "graderType": descriptor.metadata.get('format', u"Not Graded"),
+ "graderType": descriptor.lms.format or 'Not Graded',
"location": location,
"id": 99 # just an arbitrary value to
}
diff --git a/common/djangoapps/terrain/factories.py b/common/djangoapps/terrain/factories.py
index bb7ae012c8..3bedcd87aa 100644
--- a/common/djangoapps/terrain/factories.py
+++ b/common/djangoapps/terrain/factories.py
@@ -7,13 +7,14 @@ from xmodule.modulestore.django import modulestore
from time import gmtime
from uuid import uuid4
from xmodule.timeparse import stringify_time
+from xmodule.modulestore.inheritance import own_metadata
class GroupFactory(Factory):
FACTORY_FOR = Group
name = 'staff_MITx/999/Robot_Super_Course'
-
+
class UserProfileFactory(Factory):
FACTORY_FOR = UserProfile
@@ -81,18 +82,18 @@ class XModuleCourseFactory(Factory):
# This metadata code was copied from cms/djangoapps/contentstore/views.py
if display_name is not None:
- new_course.metadata['display_name'] = display_name
+ new_course.lms.display_name = display_name
- new_course.metadata['data_dir'] = uuid4().hex
- new_course.metadata['start'] = stringify_time(gmtime())
+ new_course.data_dir = uuid4().hex
+ new_course.lms.start = gmtime()
new_course.tabs = [{"type": "courseware"},
- {"type": "course_info", "name": "Course Info"},
+ {"type": "course_info", "name": "Course Info"},
{"type": "discussion", "name": "Discussion"},
{"type": "wiki", "name": "Wiki"},
{"type": "progress", "name": "Progress"}]
# Update the data in the mongo datastore
- store.update_metadata(new_course.location.url(), new_course.own_metadata)
+ store.update_metadata(new_course.location.url(), own_metadata(new_course))
return new_course
@@ -140,16 +141,16 @@ class XModuleItemFactory(Factory):
new_item = store.clone_item(template, dest_location)
# TODO: This needs to be deleted when we have proper storage for static content
- new_item.metadata['data_dir'] = parent.metadata['data_dir']
+ new_item.data_dir = parent.data_dir
# replace the display name with an optional parameter passed in from the caller
if display_name is not None:
- new_item.metadata['display_name'] = display_name
+ new_item.lms.display_name = display_name
store.update_metadata(new_item.location.url(), new_item.own_metadata)
if new_item.location.category not in DETACHED_CATEGORIES:
- store.update_children(parent_location, parent.definition.get('children', []) + [new_item.location.url()])
+ store.update_children(parent_location, parent.children + [new_item.location.url()])
return new_item
diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py
index a4f12eed94..f322d34c08 100644
--- a/common/lib/xmodule/xmodule/course_module.py
+++ b/common/lib/xmodule/xmodule/course_module.py
@@ -175,6 +175,9 @@ class CourseDescriptor(SequenceDescriptor):
no_grade = Boolean(help="True if this course isn't graded", default=False, scope=Scope.settings)
disable_progress_graph = Boolean(help="True if this course shouldn't display the progress graph", default=False, scope=Scope.settings)
pdf_textbooks = List(help="List of dictionaries containing pdf_textbook configuration", default=None, scope=Scope.settings)
+ remote_gradebook = String(scope=Scope.settings, default='')
+ allow_anonymous = Boolean(scope=Scope.settings, default=True)
+ allow_anonymous_to_peers = Boolean(scope=Scope.settings, default=False)
has_children = True
info_sidebar_name = String(scope=Scope.settings, default='Course Handouts')
diff --git a/common/lib/xmodule/xmodule/foldit_module.py b/common/lib/xmodule/xmodule/foldit_module.py
index 3990a61183..84deb1bb61 100644
--- a/common/lib/xmodule/xmodule/foldit_module.py
+++ b/common/lib/xmodule/xmodule/foldit_module.py
@@ -7,6 +7,7 @@ from pkg_resources import resource_string
from xmodule.editing_module import EditingDescriptor
from xmodule.x_module import XModule
from xmodule.xml_module import XmlDescriptor
+from xblock.core import Scope, Integer, String
log = logging.getLogger(__name__)
@@ -14,10 +15,16 @@ class FolditModule(XModule):
css = {'scss': [resource_string(__name__, 'css/foldit/leaderboard.scss')]}
- def __init__(self, system, location, definition, descriptor,
- instance_state=None, shared_state=None, **kwargs):
- XModule.__init__(self, system, location, definition, descriptor,
- instance_state, shared_state, **kwargs)
+ # default to what Spring_7012x uses
+ required_level = Integer(default=4, scope=Scope.settings)
+ required_sublevel = Integer(default=5, scope=Scope.settings)
+ due = String(help="Date that this problem is due by", scope=Scope.settings, default='')
+
+ show_basic_score = String(scope=Scope.settings, default='false')
+ show_leaderboard = String(scope=Scope.settings, default='false')
+
+ def __init__(self, *args, **kwargs):
+ XModule.__init__(self, *args, **kwargs)
"""
Example:
@@ -26,25 +33,17 @@ class FolditModule(XModule):
required_sublevel="3"
show_leaderboard="false"/>
"""
- req_level = self.metadata.get("required_level")
- req_sublevel = self.metadata.get("required_sublevel")
-
- # default to what Spring_7012x uses
- self.required_level = req_level if req_level else 4
- self.required_sublevel = req_sublevel if req_sublevel else 5
-
def parse_due_date():
"""
Pull out the date, or None
"""
- s = self.metadata.get("due")
+ s = self.due
if s:
return parser.parse(s)
else:
return None
- self.due_str = self.metadata.get("due", "None")
- self.due = parse_due_date()
+ self.due_time = parse_due_date()
def is_complete(self):
"""
@@ -59,7 +58,7 @@ class FolditModule(XModule):
self.system.anonymous_student_id,
self.required_level,
self.required_sublevel,
- self.due)
+ self.due_time)
return complete
def completed_puzzles(self):
@@ -96,10 +95,10 @@ class FolditModule(XModule):
self.required_level,
self.required_sublevel)
- showbasic = (self.metadata.get("show_basic_score").lower() == "true")
- showleader = (self.metadata.get("show_leaderboard").lower() == "true")
+ showbasic = (self.show_basic_score.lower() == "true")
+ showleader = (self.show_leaderboard.lower() == "true")
context = {
- 'due': self.due_str,
+ 'due': self.due,
'success': self.is_complete(),
'goal_level': goal_level,
'completed': self.completed_puzzles(),
@@ -121,7 +120,7 @@ class FolditModule(XModule):
self.required_sublevel)
context = {
- 'due': self.due_str,
+ 'due': self.due,
'success': self.is_complete(),
'goal_level': goal_level,
'completed': self.completed_puzzles(),
@@ -170,9 +169,4 @@ class FolditDescriptor(XmlDescriptor, EditingDescriptor):
# so always need to actually check.
always_recalculate_grades = True
- @classmethod
- def definition_from_xml(cls, xml_object, system):
- """
- Get the xml_object's attributes.
- """
- return {'metadata': xml_object.attrib}
+ metadata_attributes = XmlDescriptor.metadata_attributes + ('required_level', 'required_sublevel')
diff --git a/common/lib/xmodule/xmodule/modulestore/xml_importer.py b/common/lib/xmodule/xmodule/modulestore/xml_importer.py
index 52c695a9eb..8ad18f7a4c 100644
--- a/common/lib/xmodule/xmodule/modulestore/xml_importer.py
+++ b/common/lib/xmodule/xmodule/modulestore/xml_importer.py
@@ -109,8 +109,8 @@ def import_module_from_xml(modulestore, static_content_store, course_data_path,
course=target_location_namespace.course, name=target_location_namespace.name)
# then remap children pointers since they too will be re-namespaced
- children_locs = module.definition.get('children')
- if children_locs is not None:
+ if module.has_children:
+ children_locs = module.children
new_locs = []
for child in children_locs:
child_loc = Location(child)
@@ -119,7 +119,7 @@ def import_module_from_xml(modulestore, static_content_store, course_data_path,
new_locs.append(new_child_loc.url())
- module.definition['children'] = new_locs
+ module.children = new_locs
if hasattr(module, 'data'):
# cdodge: now go through any link references to '/static/' and make sure we've imported
@@ -237,7 +237,7 @@ def validate_category_hierarchy(module_store, course_id, parent_category, expect
parents.append(module)
for parent in parents:
- for child_loc in [Location(child) for child in parent.definition.get('children', [])]:
+ for child_loc in [Location(child) for child in parent.children]:
if child_loc.category != expected_child_category:
err_cnt += 1
print 'ERROR: child {0} of parent {1} was expected to be category of {2} but was {3}'.format(
diff --git a/common/lib/xmodule/xmodule/videoalpha_module.py b/common/lib/xmodule/xmodule/videoalpha_module.py
index 5a8504de3a..c98fcec075 100644
--- a/common/lib/xmodule/xmodule/videoalpha_module.py
+++ b/common/lib/xmodule/xmodule/videoalpha_module.py
@@ -11,6 +11,7 @@ from xmodule.raw_module import RawDescriptor
from xmodule.modulestore.mongo import MongoModuleStore
from xmodule.modulestore.django import modulestore
from xmodule.contentstore.content import StaticContent
+from xblock.core import Integer, Scope, String
import datetime
import time
@@ -46,11 +47,13 @@ class VideoAlphaModule(XModule):
css = {'scss': [resource_string(__name__, 'css/videoalpha/display.scss')]}
js_module_name = "VideoAlpha"
- def __init__(self, system, location, definition, descriptor,
- instance_state=None, shared_state=None, **kwargs):
- XModule.__init__(self, system, location, definition, descriptor,
- instance_state, shared_state, **kwargs)
- xmltree = etree.fromstring(self.definition['data'])
+ data = String(help="XML data for the problem", scope=Scope.content)
+ position = Integer(help="Current position in the video", scope=Scope.student_state, default=0)
+ display_name = String(help="Display name for this module", scope=Scope.settings)
+
+ def __init__(self, *args, **kwargs):
+ XModule.__init__(self, *args, **kwargs)
+ xmltree = etree.fromstring(self.data)
self.youtube_streams = xmltree.get('youtube')
self.sub = xmltree.get('sub')
self.position = 0
@@ -64,11 +67,6 @@ class VideoAlphaModule(XModule):
self.track = self._get_track(xmltree)
self.start_time, self.end_time = self._get_timeframe(xmltree)
- if instance_state is not None:
- state = json.loads(instance_state)
- if 'position' in state:
- self.position = int(float(state['position']))
-
def _get_source(self, xmltree, exts=None):
"""Find the first valid source, which ends with one of `exts`."""
exts = ['mp4', 'ogv', 'avi', 'webm'] if exts is None else exts
@@ -131,7 +129,7 @@ class VideoAlphaModule(XModule):
else:
# VS[compat]
# cdodge: filesystem static content support.
- caption_asset_path = "/static/{0}/subs/".format(self.metadata['data_dir'])
+ caption_asset_path = "/static/{0}/subs/".format(getattr(self, 'data_dir', None))
return self.system.render_template('videoalpha.html', {
'youtube_streams': self.youtube_streams,
@@ -141,7 +139,7 @@ class VideoAlphaModule(XModule):
'track': self.track,
'display_name': self.display_name,
# TODO (cpennington): This won't work when we move to data that isn't on the filesystem
- 'data_dir': self.metadata['data_dir'],
+ 'data_dir': getattr(self, 'data_dir', None),
'caption_asset_path': caption_asset_path,
'show_captions': self.show_captions,
'start': self.start_time,
diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py
index 12330865e7..20d1a19c50 100644
--- a/lms/djangoapps/courseware/courses.py
+++ b/lms/djangoapps/courseware/courses.py
@@ -250,7 +250,7 @@ def get_course_syllabus_section(course, section_key):
with fs.open(filepath) as htmlFile:
return replace_static_urls(
htmlFile.read().decode('utf-8'),
- course.metadata['data_dir'],
+ getattr(course, 'data_dir', None),
course_namespace=course.location
)
except ResourceNotFoundError:
diff --git a/lms/djangoapps/courseware/features/courses.py b/lms/djangoapps/courseware/features/courses.py
index ba0bcd359b..7d58dde138 100644
--- a/lms/djangoapps/courseware/features/courses.py
+++ b/lms/djangoapps/courseware/features/courses.py
@@ -26,8 +26,8 @@ def get_courseware_with_tabs(course_id):
top three levels of navigation. Same as get_courseware() except include
the tabs on the right hand main navigation page.
- This hides the appropriate courseware as defined by the XML flag test:
- chapter.metadata.get('hide_from_toc','false').lower() == 'true'
+ This hides the appropriate courseware as defined by the hide_from_toc field:
+ chapter.lms.hide_from_toc
Example:
@@ -80,14 +80,14 @@ def get_courseware_with_tabs(course_id):
"""
course = get_course_by_id(course_id)
- chapters = [chapter for chapter in course.get_children() if chapter.metadata.get('hide_from_toc', 'false').lower() != 'true']
+ chapters = [chapter for chapter in course.get_children() if not chapter.lms.hide_from_toc]
courseware = [{'chapter_name': c.display_name,
'sections': [{'section_name': s.display_name,
'clickable_tab_count': len(s.get_children()) if (type(s) == seq_module.SequenceDescriptor) else 0,
'tabs': [{'children_count': len(t.get_children()) if (type(t) == vertical_module.VerticalDescriptor) else 0,
'class': t.__class__.__name__}
for t in s.get_children()]}
- for s in c.get_children() if s.metadata.get('hide_from_toc', 'false').lower() != 'true']}
+ for s in c.get_children() if not s.lms.hide_from_toc]}
for c in chapters]
return courseware
diff --git a/lms/djangoapps/courseware/tests/test_access.py b/lms/djangoapps/courseware/tests/test_access.py
index acb05d5d78..f894b6ce5f 100644
--- a/lms/djangoapps/courseware/tests/test_access.py
+++ b/lms/djangoapps/courseware/tests/test_access.py
@@ -88,7 +88,6 @@ class AccessTestCase(TestCase):
yesterday = time.gmtime(time.time() - 86400)
tomorrow = time.gmtime(time.time() + 86400)
c = Mock(enrollment_start=yesterday, enrollment_end=tomorrow)
- c.metadata.get = 'is_public'
# User can enroll if it is between the start and end dates
self.assertTrue(access._has_access_course_desc(u, c, 'enroll'))
@@ -99,7 +98,6 @@ class AccessTestCase(TestCase):
u.is_authenticated.return_value = True
c = Mock(enrollment_start=tomorrow, enrollment_end=tomorrow, id='edX/test/2012_Fall')
- c.metadata.get = 'is_public'
allowed = CourseEnrollmentAllowedFactory(email=u.email, course_id=c.id)
@@ -110,7 +108,6 @@ class AccessTestCase(TestCase):
u.is_authenticated.return_value = True
c = Mock(enrollment_start=tomorrow, enrollment_end=tomorrow, id='edX/test/Whenever')
- c.metadata.get = 'is_public'
self.assertTrue(access._has_access_course_desc(u, c, 'enroll'))
# TODO:
diff --git a/lms/djangoapps/courseware/tests/tests.py b/lms/djangoapps/courseware/tests/tests.py
index c538ddded5..cd845b1e44 100644
--- a/lms/djangoapps/courseware/tests/tests.py
+++ b/lms/djangoapps/courseware/tests/tests.py
@@ -325,7 +325,7 @@ class PageLoader(ActivateLoginTestCase):
num_bad += 1
elif isinstance(descriptor, ErrorDescriptor):
msg = "ERROR error descriptor loaded: "
- msg = msg + descriptor.definition['data']['error_msg']
+ msg = msg + descriptor.error_msg
all_ok = False
num_bad += 1
diff --git a/lms/djangoapps/courseware/views.py b/lms/djangoapps/courseware/views.py
index c851628c1d..2278ea67b4 100644
--- a/lms/djangoapps/courseware/views.py
+++ b/lms/djangoapps/courseware/views.py
@@ -194,7 +194,7 @@ def check_for_active_timelimit_module(request, course_id, course):
# This value should be in milliseconds.
remaining_time = timelimit_module.get_remaining_time_in_ms()
context['timer_expiration_duration'] = remaining_time
- context['suppress_toplevel_navigation'] = timelimit_descriptor.metadata.suppress_toplevel_navigation
+ context['suppress_toplevel_navigation'] = timelimit_descriptor.suppress_toplevel_navigation
return_url = reverse('jump_to', kwargs={'course_id': course_id, 'location': location})
context['timer_navigation_return_url'] = return_url
return context
diff --git a/lms/djangoapps/django_comment_client/base/views.py b/lms/djangoapps/django_comment_client/base/views.py
index d93ea19f44..11a5a639a9 100644
--- a/lms/djangoapps/django_comment_client/base/views.py
+++ b/lms/djangoapps/django_comment_client/base/views.py
@@ -72,17 +72,17 @@ def create_thread(request, course_id, commentable_id):
course = get_course_with_access(request.user, course_id, 'load')
post = request.POST
- if course.metadata.get("allow_anonymous", True):
+ if course.allow_anonymous:
anonymous = post.get('anonymous', 'false').lower() == 'true'
else:
anonymous = False
- if course.metadata.get("allow_anonymous_to_peers", False):
+ if course.allow_anonymous_to_peers:
anonymous_to_peers = post.get('anonymous_to_peers', 'false').lower() == 'true'
else:
anonymous_to_peers = False
- thread = cc.Thread(**extract(post, ['body', 'title', 'tags']))
+ thread = cc.Thread(**extract(post,/ ['body', 'title', 'tags']))
thread.update_attributes(**{
'anonymous': anonymous,
'anonymous_to_peers': anonymous_to_peers,
@@ -96,7 +96,7 @@ def create_thread(request, course_id, commentable_id):
#kevinchugh because the new requirement is that all groups will be determined
#by the group id in the request this all goes away
#not anymore, only for admins
-
+
# Cohort the thread if the commentable is cohorted.
if is_commentable_cohorted(course_id, commentable_id):
user_group_id = get_cohort_id(user, course_id)
@@ -113,7 +113,7 @@ def create_thread(request, course_id, commentable_id):
if group_id:
thread.update_attributes(group_id=group_id)
-
+
thread.save()
if post.get('auto_subscribe', 'false').lower() == 'true':
@@ -147,12 +147,12 @@ def _create_comment(request, course_id, thread_id=None, parent_id=None):
comment = cc.Comment(**extract(post, ['body']))
course = get_course_with_access(request.user, course_id, 'load')
- if course.metadata.get("allow_anonymous", True):
+ if course.allow_anonymous:
anonymous = post.get('anonymous', 'false').lower() == 'true'
else:
anonymous = False
- if course.metadata.get("allow_anonymous_to_peers", False):
+ if course.allow_anonymous_to_peers:
anonymous_to_peers = post.get('anonymous_to_peers', 'false').lower() == 'true'
else:
anonymous_to_peers = False
diff --git a/lms/djangoapps/django_comment_client/forum/views.py b/lms/djangoapps/django_comment_client/forum/views.py
index a3120c563a..07309a2847 100644
--- a/lms/djangoapps/django_comment_client/forum/views.py
+++ b/lms/djangoapps/django_comment_client/forum/views.py
@@ -124,31 +124,31 @@ def inline_discussion(request, course_id, discussion_id):
annotated_content_info = utils.get_metadata_for_threads(course_id, threads, request.user, user_info)
- allow_anonymous = course.metadata.get("allow_anonymous", True)
- allow_anonymous_to_peers = course.metadata.get("allow_anonymous_to_peers", False)
+ allow_anonymous = course.allow_anonymous
+ allow_anonymous_to_peers = course.allow_anonymous_to_peers
#since inline is all one commentable, only show or allow the choice of cohorts
#if the commentable is cohorted, otherwise everything is not cohorted
#and no one has the option of choosing a cohort
is_cohorted = is_course_cohorted(course_id) and is_commentable_cohorted(course_id, discussion_id)
is_moderator = cached_has_permission(request.user, "see_all_cohorts", course_id)
-
+
cohorts_list = list()
-
+
if is_cohorted:
cohorts_list.append({'name':'All Groups','id':None})
-
+
#if you're a mod, send all cohorts and let you pick
-
+
if is_moderator:
cohorts = get_course_cohorts(course_id)
for c in cohorts:
cohorts_list.append({'name':c.name, 'id':c.id})
-
+
else:
#students don't get to choose
cohorts_list = None
-
+
return utils.JsonResponse({
'discussion_data': map(utils.safe_content, threads),
'user_info': user_info,
diff --git a/lms/djangoapps/django_comment_client/tests.py b/lms/djangoapps/django_comment_client/tests.py
index 4b5fe2ba5a..1d925cdb8e 100644
--- a/lms/djangoapps/django_comment_client/tests.py
+++ b/lms/djangoapps/django_comment_client/tests.py
@@ -62,7 +62,7 @@ from courseware.tests.tests import PageLoader, TEST_DATA_XML_MODULESTORE
# #self.assertEqual(resp.status_code, 200)
# #self.assertEqual(my_save.something, "expected", "complaint if not true")
#
-# self.toy.metadata["cohort_config"] = {"cohorted": True}
+# self.toy.cohort_config = {"cohorted": True}
#
# # call the view again ...
#
diff --git a/lms/djangoapps/django_comment_client/utils.py b/lms/djangoapps/django_comment_client/utils.py
index 3bd2ce8644..0e9b398bc6 100644
--- a/lms/djangoapps/django_comment_client/utils.py
+++ b/lms/djangoapps/django_comment_client/utils.py
@@ -173,8 +173,8 @@ def initialize_discussion_info(course):
path_to_locations = {}
for module in all_modules:
skip_module = False
- for key in ('id', 'discussion_category', 'for'):
- if key not in module.metadata:
+ for key in ('discussion_id', 'discussion_category', 'discussion_target'):
+ if getattr(module, key) is None:
log.warning("Required key '%s' not in discussion %s, leaving out of category map" % (key, module.location))
skip_module = True
diff --git a/lms/djangoapps/instructor/views.py b/lms/djangoapps/instructor/views.py
index d57d99f2ff..018f7e4313 100644
--- a/lms/djangoapps/instructor/views.py
+++ b/lms/djangoapps/instructor/views.py
@@ -136,7 +136,7 @@ def instructor_dashboard(request, course_id):
if settings.MITX_FEATURES['ENABLE_MANUAL_GIT_RELOAD']:
if 'GIT pull' in action:
- data_dir = course.metadata['data_dir']
+ data_dir = getattr(course, 'data_dir')
log.debug('git pull {0}'.format(data_dir))
gdir = settings.DATA_DIR / data_dir
if not os.path.exists(gdir):
@@ -150,7 +150,7 @@ def instructor_dashboard(request, course_id):
if 'Reload course' in action:
log.debug('reloading {0} ({1})'.format(course_id, course))
try:
- data_dir = course.metadata['data_dir']
+ data_dir = getattr(course, 'data_dir')
modulestore().try_load_course(data_dir)
msg += "
Course reloaded from {0}
".format(data_dir) track.views.server_track(request, 'reload {0}'.format(data_dir), {}, page='idashboard') @@ -404,7 +404,7 @@ def instructor_dashboard(request, course_id): def getdat(u): p = u.profile return [u.username, u.email] + [getattr(p,x,'') for x in profkeys] - + datatable['data'] = [getdat(u) for u in enrolled_students] datatable['title'] = 'Student profile data for course %s' % course_id return return_csv('profiledata_%s.csv' % course_id, datatable) @@ -426,7 +426,7 @@ def instructor_dashboard(request, course_id): msg+="Couldn't find module with that urlname. " msg += "%s" % escape(err) smdat = [] - + if smdat: datatable = {'header': ['username', 'state']} datatable['data'] = [ [x.student.username, x.state] for x in smdat ] @@ -621,7 +621,7 @@ def _do_remote_gradebook(user, course, action, args=None, files=None): ''' Perform remote gradebook action. Returns msg, datatable. ''' - rg = course.metadata.get('remote_gradebook', '') + rg = course.remote_gradebook if not rg: msg = "No remote gradebook defined in course metadata" return msg, {} diff --git a/lms/djangoapps/staticbook/views.py b/lms/djangoapps/staticbook/views.py index a391b1cb32..281bfbfcdd 100644 --- a/lms/djangoapps/staticbook/views.py +++ b/lms/djangoapps/staticbook/views.py @@ -46,7 +46,7 @@ def pdf_index(request, course_id, book_index, chapter=None, page=None): input_url = "'" + original_url + "'" output_url = replace_static_urls( input_url, - course.metadata['data_dir'], + getattr(course, 'data_dir', None), course_namespace=course.location ) # strip off the quotes again... @@ -57,12 +57,12 @@ def pdf_index(request, course_id, book_index, chapter=None, page=None): # then remap all the chapter URLs as well, if they are provided. if 'chapters' in textbook: for entry in textbook['chapters']: - entry['url'] = remap_static_url(entry['url'], course) + entry['url'] = remap_static_url(entry['url'], course) return render_to_response('static_pdfbook.html', - {'book_index': book_index, - 'course': course, + {'book_index': book_index, + 'course': course, 'textbook': textbook, 'chapter': chapter, 'page': page,