Commit 7a238935 by Chris Dodge

wip

parent a603f254
import logging
from django.conf import settings
from xmodule.modulestore import Location
from xmodule.modulestore.django import modulestore
......@@ -127,7 +128,7 @@ class UnitState(object):
public = 'public'
def compute_unit_state(unit):
def compute_unit_state(unit, subsection=None):
"""
Returns whether this unit is 'draft', 'public', or 'private'.
......@@ -137,7 +138,8 @@ def compute_unit_state(unit):
'private' content is editabled and not visible in the LMS
"""
if unit.cms.is_draft:
logging.debug('****** is_draft = {0}'.format(getattr(unit, 'is_draft', False)))
if getattr(unit, 'is_draft', False):
try:
modulestore('direct').get_item(unit.location)
return UnitState.draft
......
......@@ -188,7 +188,7 @@ def course_index(request, org, course, name):
'coursename': name
})
course = modulestore().get_item(location)
course = modulestore().get_item(location, depth=3)
sections = course.get_children()
return render_to_response('overview.html', {
......
......@@ -13,7 +13,7 @@ This def will enumerate through a passed in subsection and list all of the units
% for unit in subsection_units:
<li class="leaf unit" data-id="${unit.location}">
<%
unit_state = compute_unit_state(unit)
unit_state = compute_unit_state(unit, subsection=subsection)
if unit.location == selected:
selected_class = 'editing'
else:
......
......@@ -40,7 +40,6 @@ class CmsNamespace(Namespace):
"""
Namespace with fields common to all blocks in Studio
"""
is_draft = Boolean(help="Whether this module is a draft", default=False, scope=Scope.settings)
published_date = DateTuple(help="Date when the module was published", scope=Scope.settings)
published_by = String(help="Id of the user who published this module", scope=Scope.settings)
empty = StringyBoolean(help="Whether this is an empty template", scope=Scope.settings, default=False)
......@@ -10,6 +10,7 @@ from collections import namedtuple
from .exceptions import InvalidLocationError, InsufficientSpecificationError
from xmodule.errortracker import ErrorLog, make_error_tracker
from bson.son import SON
log = logging.getLogger('mitx.' + 'modulestore')
......@@ -457,3 +458,13 @@ class ModuleStoreBase(ModuleStore):
if c.id == course_id:
return c
return None
def namedtuple_to_son(namedtuple, prefix=''):
"""
Converts a namedtuple into a SON object with the same key order
"""
son = SON()
for idx, field_name in enumerate(namedtuple._fields):
son[prefix + field_name] = namedtuple[idx]
return son
from datetime import datetime
from . import ModuleStoreBase, Location
from . import ModuleStoreBase, Location, namedtuple_to_son
from .exceptions import ItemNotFoundError
import logging
DRAFT = 'draft'
......@@ -15,11 +16,11 @@ def as_draft(location):
def wrap_draft(item):
"""
Sets `item.cms.is_draft` to `True` if the item is a
Sets `item.is_draft` to `True` if the item is a
draft, and `False` otherwise. Sets the item's location to the
non-draft location in either case
"""
item.cms.is_draft = item.location.revision == DRAFT
setattr(item, 'is_draft', item.location.revision == DRAFT)
item.location = item.location._replace(revision=None)
return item
......@@ -55,11 +56,10 @@ class DraftModuleStore(ModuleStoreBase):
get_children() to cache. None indicates to cache all descendents
"""
# cdodge: we're forcing depth=0 here as the Draft store is not handling caching well
try:
return wrap_draft(super(DraftModuleStore, self).get_item(as_draft(location), depth=0))
return wrap_draft(super(DraftModuleStore, self).get_item(as_draft(location), depth=depth))
except ItemNotFoundError:
return wrap_draft(super(DraftModuleStore, self).get_item(location, depth=0))
return wrap_draft(super(DraftModuleStore, self).get_item(location, depth=depth))
def get_instance(self, course_id, location, depth=0):
"""
......@@ -67,11 +67,10 @@ class DraftModuleStore(ModuleStoreBase):
TODO (vshnayder): this may want to live outside the modulestore eventually
"""
# cdodge: we're forcing depth=0 here as the Draft store is not handling caching well
try:
return wrap_draft(super(DraftModuleStore, self).get_instance(course_id, as_draft(location), depth=0))
return wrap_draft(super(DraftModuleStore, self).get_instance(course_id, as_draft(location), depth=depth))
except ItemNotFoundError:
return wrap_draft(super(DraftModuleStore, self).get_instance(course_id, location, depth=0))
return wrap_draft(super(DraftModuleStore, self).get_instance(course_id, location, depth=depth))
def get_items(self, location, course_id=None, depth=0):
"""
......@@ -88,9 +87,8 @@ class DraftModuleStore(ModuleStoreBase):
"""
draft_loc = as_draft(location)
# cdodge: we're forcing depth=0 here as the Draft store is not handling caching well
draft_items = super(DraftModuleStore, self).get_items(draft_loc, course_id=course_id, depth=0)
items = super(DraftModuleStore, self).get_items(location, course_id=course_id, depth=0)
draft_items = super(DraftModuleStore, self).get_items(draft_loc, course_id=course_id, depth=depth)
items = super(DraftModuleStore, self).get_items(location, course_id=course_id, depth=depth)
draft_locs_found = set(item.location._replace(revision=None) for item in draft_items)
non_draft_items = [
......@@ -118,7 +116,7 @@ class DraftModuleStore(ModuleStoreBase):
"""
draft_loc = as_draft(location)
draft_item = self.get_item(location)
if not draft_item.cms.is_draft:
if not getattr(draft_item, 'is_draft', False):
self.clone_item(location, draft_loc)
return super(DraftModuleStore, self).update_item(draft_loc, data)
......@@ -133,7 +131,7 @@ class DraftModuleStore(ModuleStoreBase):
"""
draft_loc = as_draft(location)
draft_item = self.get_item(location)
if not draft_item.cms.is_draft:
if not getattr(draft_item, 'is_draft', False):
self.clone_item(location, draft_loc)
return super(DraftModuleStore, self).update_children(draft_loc, children)
......@@ -149,7 +147,7 @@ class DraftModuleStore(ModuleStoreBase):
draft_loc = as_draft(location)
draft_item = self.get_item(location)
if not draft_item.cms.is_draft:
if not getattr(draft_item, 'is_draft', False):
self.clone_item(location, draft_loc)
if 'is_draft' in metadata:
......@@ -192,3 +190,44 @@ class DraftModuleStore(ModuleStoreBase):
"""
super(DraftModuleStore, self).clone_item(location, as_draft(location))
super(DraftModuleStore, self).delete_item(location)
def _cache_children(self, items, depth=0):
"""
Returns a dictionary mapping Location -> item data, populated with json data
for all descendents of items up to the specified depth.
(0 = no descendents, 1 = children, 2 = grandchildren, etc)
If depth is None, will load all the children.
This will make a number of queries that is linear in the depth.
"""
data = {}
to_process = list(items)
while to_process and depth is None or depth >= 0:
children = []
for item in to_process:
self._clean_item_data(item)
children.extend(item.get('definition', {}).get('children', []))
data[Location(item['location'])] = item
# Load all children by id. See
# http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24or
# for or-query syntax
if children:
query = {
'_id': {'$in': [namedtuple_to_son(Location(child)) for child in children]}
}
to_process = list(self.collection.find(query))
query = {
'_id': {'$in': [namedtuple_to_son(as_draft(Location(child))) for child in children]}
}
to_process.extend(list(self.collection.find(query)))
logging.debug('**** depth = {0}'.format(depth))
logging.debug('**** to_process = {0}'.format(to_process))
else:
to_process = []
# If depth is None, then we just recurse until we hit all the descendents
if depth is not None:
depth -= 1
return data
\ No newline at end of file
......@@ -3,7 +3,6 @@ import sys
import logging
import copy
from bson.son import SON
from collections import namedtuple
from fs.osfs import OSFS
from itertools import repeat
......@@ -18,7 +17,7 @@ from xmodule.error_module import ErrorDescriptor
from xblock.runtime import DbModel, KeyValueStore, InvalidScopeError
from xblock.core import Scope
from . import ModuleStoreBase, Location
from . import ModuleStoreBase, Location, namedtuple_to_son
from .draft import DraftModuleStore
from .exceptions import (ItemNotFoundError,
DuplicateItemError)
......@@ -196,16 +195,6 @@ def location_to_query(location, wildcard=True):
return query
def namedtuple_to_son(namedtuple, prefix=''):
"""
Converts a namedtuple into a SON object with the same key order
"""
son = SON()
for idx, field_name in enumerate(namedtuple._fields):
son[prefix + field_name] = namedtuple[idx]
return son
class MongoModuleStore(ModuleStoreBase):
"""
A Mongodb backed ModuleStore
......@@ -372,13 +361,14 @@ class MongoModuleStore(ModuleStoreBase):
# Load all children by id. See
# http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24or
# for or-query syntax
if children:
if children and depth > 0:
query = {
'_id': {'$in': [namedtuple_to_son(Location(child)) for child in children]}
}
to_process = self.collection.find(query)
to_process = list(self.collection.find(query))
else:
to_process = []
break
# If depth is None, then we just recurse until we hit all the descendents
if depth is not None:
depth -= 1
......
......@@ -136,3 +136,4 @@ def delete_course(modulestore, contentstore, source_location, commit = False):
modulestore.delete_item(source_location)
return True
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment