Successfully read course children out of mongodb
This commit is contained in:
@@ -6,11 +6,13 @@
|
|||||||
#import mitxmako.middleware
|
#import mitxmako.middleware
|
||||||
#from courseware import content_parser
|
#from courseware import content_parser
|
||||||
#from django.contrib.auth.models import User
|
#from django.contrib.auth.models import User
|
||||||
|
import os.path
|
||||||
|
from StringIO import StringIO
|
||||||
from mako.template import Template
|
from mako.template import Template
|
||||||
from mako.lookup import TemplateLookup
|
from mako.lookup import TemplateLookup
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
from contentstore.models import create_item, update_item, update_children
|
from keystore.django import keystore
|
||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
@@ -20,16 +22,15 @@ class Command(BaseCommand):
|
|||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
print args
|
print args
|
||||||
data_dir = args[0]
|
data_dir = args[0]
|
||||||
course_file = 'course.xml'
|
|
||||||
|
|
||||||
parser = etree.XMLParser(remove_comments = True)
|
parser = etree.XMLParser(remove_comments = True)
|
||||||
|
|
||||||
lookup = TemplateLookup(directories=[data_dir])
|
lookup = TemplateLookup(directories=[data_dir])
|
||||||
template = lookup.get_template("course.xml")
|
template = lookup.get_template("course.xml")
|
||||||
course_string = template.render(groups=[])
|
course_string = template.render(groups=[])
|
||||||
course = etree.XML(course_string, parser=parser)
|
course = etree.parse(StringIO(course_string), parser=parser)
|
||||||
|
|
||||||
elements = course.xpath("//*")
|
elements = list(course.iter())
|
||||||
|
|
||||||
tag_to_category = {# Inside HTML ==> Skip these
|
tag_to_category = {# Inside HTML ==> Skip these
|
||||||
# Custom tags
|
# Custom tags
|
||||||
@@ -39,11 +40,11 @@ class Command(BaseCommand):
|
|||||||
'image': 'Custom',
|
'image': 'Custom',
|
||||||
'discuss': 'Custom',
|
'discuss': 'Custom',
|
||||||
# Simple lists
|
# Simple lists
|
||||||
'chapter': 'Sequence',
|
'chapter': 'Chapter',
|
||||||
'course': 'Sequence',
|
'course': 'Course',
|
||||||
'sequential': 'Sequence',
|
'sequential': 'LectureSequence',
|
||||||
'vertical': 'Sequence',
|
'vertical': 'ProblemSet',
|
||||||
'section': 'Sequence',
|
'section': 'Section',
|
||||||
# True types
|
# True types
|
||||||
'video': 'VideoSegment',
|
'video': 'VideoSegment',
|
||||||
'html': 'HTML',
|
'html': 'HTML',
|
||||||
@@ -114,7 +115,7 @@ class Command(BaseCommand):
|
|||||||
results[e.attrib['url']] = {'data':{'text':text}}
|
results[e.attrib['url']] = {'data':{'text':text}}
|
||||||
|
|
||||||
def handle_problem(e):
|
def handle_problem(e):
|
||||||
data = open(data_dir+'problems/'+e.attrib['filename']+'.xml').read()
|
data = open(os.path.join(data_dir, 'problems', e.attrib['filename']+'.xml')).read()
|
||||||
results[e.attrib['url']] = {'data':{'statement':data}}
|
results[e.attrib['url']] = {'data':{'statement':data}}
|
||||||
|
|
||||||
element_actions = {# Inside HTML ==> Skip these
|
element_actions = {# Inside HTML ==> Skip these
|
||||||
@@ -149,10 +150,8 @@ class Command(BaseCommand):
|
|||||||
|
|
||||||
for k in results:
|
for k in results:
|
||||||
print k
|
print k
|
||||||
create_item(k, 'Piotr Mitros')
|
keystore.create_item(k, 'Piotr Mitros')
|
||||||
if 'data' in results[k]:
|
if 'data' in results[k]:
|
||||||
update_item(k, results[k]['data'])
|
keystore.update_item(k, results[k]['data'])
|
||||||
if 'children' in results[k]:
|
if 'children' in results[k]:
|
||||||
update_children(k, results[k]['children'])
|
keystore.update_children(k, results[k]['children'])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
from mitxmako.shortcuts import render_to_response
|
from mitxmako.shortcuts import render_to_response
|
||||||
from keystore import Location
|
|
||||||
from keystore.django import keystore
|
from keystore.django import keystore
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def calendar(request, org, course):
|
def calendar(request, org, course):
|
||||||
weeks = keystore.get_children_for_item(
|
weeks = keystore.get_children_for_item(['i4x', org, course, 'Course', None])
|
||||||
Location(['i4x', org, course, 'Course', 'course'])
|
|
||||||
)
|
|
||||||
return render_to_response('calendar.html', {'weeks': weeks})
|
return render_to_response('calendar.html', {'weeks': weeks})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,40 @@ class KeyStore(object):
|
|||||||
with the specified location.
|
with the specified location.
|
||||||
|
|
||||||
If no object is found at that location, raises keystore.exceptions.ItemNotFoundError
|
If no object is found at that location, raises keystore.exceptions.ItemNotFoundError
|
||||||
|
|
||||||
|
Searches for all matches of a partially specifed location, but raises an
|
||||||
|
keystore.exceptions.InsufficientSpecificationError if more
|
||||||
|
than a single object matches the query.
|
||||||
|
|
||||||
|
location: Something that can be passed to Location
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def create_item(self, location, editor):
|
||||||
|
"""
|
||||||
|
Create an empty item at the specified location with the supplied editor
|
||||||
|
|
||||||
|
location: Something that can be passed to Location
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def update_item(self, location, data):
|
||||||
|
"""
|
||||||
|
Set the data in the item specified by the location to
|
||||||
|
data
|
||||||
|
|
||||||
|
location: Something that can be passed to Location
|
||||||
|
data: A nested dictionary of problem data
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def update_children(self, location, children):
|
||||||
|
"""
|
||||||
|
Set the children for the item specified by the location to
|
||||||
|
data
|
||||||
|
|
||||||
|
location: Something that can be passed to Location
|
||||||
|
children: A list of child item identifiers
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|||||||
@@ -5,3 +5,7 @@ Exceptions thrown by KeyStore objects
|
|||||||
|
|
||||||
class ItemNotFoundError(Exception):
|
class ItemNotFoundError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class InsufficientSpecificationError(Exception):
|
||||||
|
pass
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import pymongo
|
import pymongo
|
||||||
from . import KeyStore
|
from . import KeyStore, Location
|
||||||
from .exceptions import ItemNotFoundError
|
from .exceptions import ItemNotFoundError, InsufficientSpecificationError
|
||||||
|
|
||||||
|
|
||||||
class MongoKeyStore(KeyStore):
|
class MongoKeyStore(KeyStore):
|
||||||
@@ -12,15 +12,64 @@ class MongoKeyStore(KeyStore):
|
|||||||
host=host,
|
host=host,
|
||||||
port=port
|
port=port
|
||||||
)[db][collection]
|
)[db][collection]
|
||||||
|
|
||||||
|
# Force mongo to report errors, at the expense of performance
|
||||||
|
self.collection.safe = True
|
||||||
|
|
||||||
def get_children_for_item(self, location):
|
def get_children_for_item(self, location):
|
||||||
item = self.collection.find_one(
|
query = dict(
|
||||||
{'location': location.dict()},
|
('location.{key}'.format(key=key), val)
|
||||||
|
for (key, val)
|
||||||
|
in Location(location).dict().items()
|
||||||
|
if val is not None
|
||||||
|
)
|
||||||
|
items = self.collection.find(
|
||||||
|
query,
|
||||||
fields={'children': True},
|
fields={'children': True},
|
||||||
sort=[('revision', pymongo.ASCENDING)],
|
sort=[('revision', pymongo.ASCENDING)],
|
||||||
|
limit=1,
|
||||||
|
)
|
||||||
|
if items.count() > 1:
|
||||||
|
raise InsufficientSpecificationError(location)
|
||||||
|
|
||||||
|
if items.count() == 0:
|
||||||
|
raise ItemNotFoundError(location)
|
||||||
|
|
||||||
|
return items[0]['children']
|
||||||
|
|
||||||
|
def create_item(self, location, editor):
|
||||||
|
"""
|
||||||
|
Create an empty item at the specified location with the supplied editor
|
||||||
|
|
||||||
|
location: Something that can be passed to Location
|
||||||
|
"""
|
||||||
|
self.collection.insert({
|
||||||
|
'location': Location(location).dict(),
|
||||||
|
'editor': editor
|
||||||
|
})
|
||||||
|
|
||||||
|
def update_item(self, location, data):
|
||||||
|
"""
|
||||||
|
Set the data in the item specified by the location to
|
||||||
|
data
|
||||||
|
|
||||||
|
location: Something that can be passed to Location
|
||||||
|
data: A nested dictionary of problem data
|
||||||
|
"""
|
||||||
|
self.collection.update(
|
||||||
|
{'location': Location(location).dict()},
|
||||||
|
{'$set': {'data': data}}
|
||||||
)
|
)
|
||||||
|
|
||||||
if item is None:
|
def update_children(self, location, children):
|
||||||
raise ItemNotFoundError()
|
"""
|
||||||
|
Set the children for the item specified by the location to
|
||||||
|
data
|
||||||
|
|
||||||
return item['children']
|
location: Something that can be passed to Location
|
||||||
|
children: A list of child item identifiers
|
||||||
|
"""
|
||||||
|
self.collection.update(
|
||||||
|
{'location': Location(location).dict()},
|
||||||
|
{'$set': {'children': children}}
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user