Commit c3a6ad2f by Bridger Maxwell

Module ids are unique even across module types. Fix bugs where other fields were…

Module ids are unique even across module types. Fix bugs where other fields were being used for an id.

--HG--
branch : profiledev
parent 4f152585
...@@ -82,40 +82,47 @@ def id_tag(course): ...@@ -82,40 +82,47 @@ def id_tag(course):
if elem.get('id'): if elem.get('id'):
pass pass
elif elem.get(default_ids[elem.tag]): elif elem.get(default_ids[elem.tag]):
new_id = elem.get(default_ids[elem.tag]) # Convert to alphanumeric new_id = elem.get(default_ids[elem.tag])
new_id = "".join([a for a in new_id if a.isalnum()]) new_id = "".join([a for a in new_id if a.isalnum()]) # Convert to alphanumeric
# Without this, a conflict may occur between an hmtl or youtube id
new_id = default_ids[elem.tag] + new_id
elem.set('id', new_id) elem.set('id', new_id)
else: else:
elem.set('id', fasthash(etree.tostring(elem))) elem.set('id', fasthash(etree.tostring(elem)))
def due_tag(element, parent_due_date=None): def propogate_downward_tag(element, attribute_name, parent_attribute = None):
''' This call is to pass down due dates. If an element has a due date, ''' This call is to pass down an attribute to all children. If an element
all of the elements children will inherit this due date (unless the element has this attribute, it will be "inherited" by all of its children. If a
has a due date of its own). This is called recursively''' child (A) already has that attribute, A will keep the same attribute and
all of A's children will inherit A's attribute. This is a recursive call.'''
if (parent_due_date == None): #This is the entry call. Select all due elements
all_due_elements = element.xpath("//*[@due]") if (parent_attribute == None): #This is the entry call. Select all due elements
for due_element in all_due_elements: all_attributed_elements = element.xpath("//*[@" + attribute_name +"]")
due_date = due_element.get('due') for attributed_element in all_attributed_elements:
for child_element in due_element: attribute_value = attributed_element.get(attribute_name)
due_tag(child_element, due_date) for child_element in attributed_element:
propogate_downward_tag(child_element, attribute_name, attribute_value)
else: else:
#The hack below is because we would get _ContentOnlyELements from the '''The hack below is because we would get _ContentOnlyELements from the
#iterator that can't have due dates set. We can't find API for it iterator that can't have due dates set. We can't find API for it. If we
if not element.get('due') and type(element) == etree._Element: ever have an element which subclasses BaseElement, we will not tag it'''
element.set('due', parent_due_date) if not element.get(attribute_name) and type(element) == etree._Element:
due_date = parent_due_date element.set(attribute_name, parent_attribute)
else:
due_date = element.get('due')
for child_element in element: for child_element in element:
due_tag(child_element, due_date) propogate_downward_tag(child_element, attribute_name, parent_attribute)
else:
#This element would have already been found by Xpath, so we return
#for now and trust that this element will get its turn to propogate
#to its children later.
return
def course_file(user): def course_file(user):
# TODO: Cache. # TODO: Cache.
tree = etree.parse(settings.DATA_DIR+UserProfile.objects.get(user=user).courseware) tree = etree.parse(settings.DATA_DIR+UserProfile.objects.get(user=user).courseware)
id_tag(tree) id_tag(tree)
due_tag(tree) propogate_downward_tag(tree, "due")
propogate_downward_tag(tree, "graded")
return tree return tree
def module_xml(coursefile, module, id_tag, module_id): def module_xml(coursefile, module, id_tag, module_id):
......
...@@ -50,7 +50,7 @@ class StudentModule(models.Model): ...@@ -50,7 +50,7 @@ class StudentModule(models.Model):
module_id = models.CharField(max_length=255) # Filename for homeworks, etc. module_id = models.CharField(max_length=255) # Filename for homeworks, etc.
student = models.ForeignKey(User) student = models.ForeignKey(User)
class Meta: class Meta:
unique_together = (('student', 'module_id', 'module_type'),) unique_together = (('student', 'module_id'),)
## Internal state of the object ## Internal state of the object
state = models.TextField(null=True, blank=True) state = models.TextField(null=True, blank=True)
......
...@@ -33,10 +33,14 @@ from django.conf import settings ...@@ -33,10 +33,14 @@ from django.conf import settings
import courseware.content_parser as content_parser import courseware.content_parser as content_parser
import sys import sys
import logging
from lxml import etree from lxml import etree
import uuid import uuid
log = logging.getLogger("mitx.courseware")
## TODO: Add registration mechanism ## TODO: Add registration mechanism
modx_modules={'problem':courseware.modules.capa_module.LoncapaModule, modx_modules={'problem':courseware.modules.capa_module.LoncapaModule,
'video':courseware.modules.video_module.VideoModule, 'video':courseware.modules.video_module.VideoModule,
...@@ -64,11 +68,10 @@ def make_track_function(request): ...@@ -64,11 +68,10 @@ def make_track_function(request):
def modx_dispatch(request, module=None, dispatch=None, id=None): def modx_dispatch(request, module=None, dispatch=None, id=None):
''' Generic view for extensions. ''' ''' Generic view for extensions. '''
# Grab the student information for the module from the database # Grab the student information for the module from the database
s = StudentModule.objects.filter(module_type=module, s = StudentModule.objects.filter(student=request.user,
student=request.user,
module_id=id) module_id=id)
if len(s) == 0: if len(s) == 0:
print "ls404", module, request.user, id log.debug("Couldnt find module for user and id " + str(module) + " " + str(request.user) + " "+ str(id))
raise Http404 raise Http404
s=s[0] s=s[0]
......
...@@ -40,13 +40,13 @@ class LoncapaModule(XModule): ...@@ -40,13 +40,13 @@ class LoncapaModule(XModule):
def get_html(self): def get_html(self):
return render_to_string('problem_ajax.html', return render_to_string('problem_ajax.html',
{'id':self.filename, {'id':self.item_id,
'ajax_url':self.ajax_url, 'ajax_url':self.ajax_url,
}) })
def get_init_js(self): def get_init_js(self):
return render_to_string('problem.js', return render_to_string('problem.js',
{'id':self.filename, {'id':self.item_id,
'ajax_url':self.ajax_url, 'ajax_url':self.ajax_url,
}) })
...@@ -94,7 +94,7 @@ class LoncapaModule(XModule): ...@@ -94,7 +94,7 @@ class LoncapaModule(XModule):
html=render_to_string('problem.html', html=render_to_string('problem.html',
{'problem' : content, {'problem' : content,
'id' : self.filename, 'id' : self.item_id,
'check_button' : check_button, 'check_button' : check_button,
'reset_button' : reset_button, 'reset_button' : reset_button,
'save_button' : save_button, 'save_button' : save_button,
......
...@@ -20,6 +20,7 @@ from lxml import etree ...@@ -20,6 +20,7 @@ from lxml import etree
from auth.models import UserProfile from auth.models import UserProfile
from models import StudentModule from models import StudentModule
from module_render import * # TODO: Clean up from module_render import * # TODO: Clean up
from module_render import modx_dispatch
import courseware.content_parser as content_parser import courseware.content_parser as content_parser
log = logging.getLogger("mitx.courseware") log = logging.getLogger("mitx.courseware")
...@@ -45,6 +46,11 @@ def profile(request): ...@@ -45,6 +46,11 @@ def profile(request):
chapters = dom.xpath('//course[@name=$course]/chapter', course=course) chapters = dom.xpath('//course[@name=$course]/chapter', course=course)
responses=StudentModule.objects.filter(student=request.user) responses=StudentModule.objects.filter(student=request.user)
response_by_id = {}
for response in responses:
response_by_id[response.module_id] = response
print response_by_id
for c in chapters: for c in chapters:
chname=c.get('name') chname=c.get('name')
...@@ -55,14 +61,15 @@ def profile(request): ...@@ -55,14 +61,15 @@ def profile(request):
scores=[] scores=[]
if len(problems)>0: if len(problems)>0:
for p in problems: for p in problems:
id = p.get('filename') id = p.get('id')
correct = 0 correct = 0
for response in responses: if id in response_by_id:
if response.module_id == id: response = response_by_id[id]
if response.grade!=None: if response.grade!=None:
correct=response.grade correct=response.grade
else: else:
correct=0 print "Couldn't find id " + id
total=courseware.modules.capa_module.LoncapaModule(etree.tostring(p), "id").max_score() # TODO: Add state. Not useful now, but maybe someday problems will have randomized max scores? total=courseware.modules.capa_module.LoncapaModule(etree.tostring(p), "id").max_score() # TODO: Add state. Not useful now, but maybe someday problems will have randomized max scores?
scores.append((int(correct),total)) scores.append((int(correct),total))
score={'course':course, score={'course':course,
......
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