Merge
--HG-- branch : bridgerwiki
This commit is contained in:
@@ -11,11 +11,12 @@ import calc, eia
|
||||
from util import contextualize_text
|
||||
|
||||
from inputtypes import textline, schematic
|
||||
from responsetypes import numericalresponse, formularesponse, customresponse
|
||||
from responsetypes import numericalresponse, formularesponse, customresponse, schematicresponse
|
||||
|
||||
response_types = {'numericalresponse':numericalresponse,
|
||||
'formularesponse':formularesponse,
|
||||
'customresponse':customresponse}
|
||||
'customresponse':customresponse,
|
||||
'schematicresponse':schematicresponse}
|
||||
entry_types = ['textline', 'schematic']
|
||||
response_properties = ["responseparam", "answer"]
|
||||
# How to convert from original XML to HTML
|
||||
@@ -23,6 +24,7 @@ response_properties = ["responseparam", "answer"]
|
||||
html_transforms = {'problem': {'tag':'div'},
|
||||
"numericalresponse": {'tag':'span'},
|
||||
"customresponse": {'tag':'span'},
|
||||
"schematicresponse": {'tag':'span'},
|
||||
"formularesponse": {'tag':'span'},
|
||||
"text": {'tag':'span'}}
|
||||
|
||||
@@ -36,7 +38,7 @@ global_context={'random':random,
|
||||
# These should be removed from HTML output, including all subelements
|
||||
html_problem_semantics = ["responseparam", "answer", "script"]
|
||||
# These should be removed from HTML output, but keeping subelements
|
||||
html_skip = ["numericalresponse", "customresponse", "formularesponse", "text"]
|
||||
html_skip = ["numericalresponse", "customresponse", "schematicresponse", "formularesponse", "text"]
|
||||
# These should be transformed
|
||||
html_special_response = {"textline":textline.render,
|
||||
"schematic":schematic.render}
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
try:
|
||||
from django.conf import settings
|
||||
from auth.models import UserProfile
|
||||
except:
|
||||
settings = None
|
||||
|
||||
from xml.dom.minidom import parse, parseString
|
||||
|
||||
from lxml import etree
|
||||
|
||||
''' This file will eventually form an abstraction layer between the
|
||||
course XML file and the rest of the system.
|
||||
|
||||
TODO: Shift everything from xml.dom.minidom to XPath (or XQuery)
|
||||
'''
|
||||
|
||||
def xpath(xml, query_string, **args):
|
||||
''' Safe xpath query into an xml tree:
|
||||
* xml is the tree.
|
||||
* query_string is the query
|
||||
* args are the parameters. Substitute for {params}.
|
||||
We should remove this with the move to lxml.
|
||||
We should also use lxml argument passing. '''
|
||||
doc = etree.fromstring(xml)
|
||||
print type(doc)
|
||||
def escape(x):
|
||||
# TODO: This should escape the string. For now, we just assume it's made of valid characters.
|
||||
# Couldn't figure out how to escape for lxml in a few quick Googles
|
||||
valid_chars="".join(map(chr, range(ord('a'),ord('z')+1)+range(ord('A'),ord('Z')+1)+range(ord('0'), ord('9')+1)))+"_ "
|
||||
for e in x:
|
||||
if e not in valid_chars:
|
||||
raise Exception("Invalid char in xpath expression. TODO: Escape")
|
||||
return x
|
||||
|
||||
args=dict( ((k, escape(args[k])) for k in args) )
|
||||
print args
|
||||
results = doc.xpath(query_string.format(**args))
|
||||
return results
|
||||
|
||||
def xpath_remove(tree, path):
|
||||
''' Remove all items matching path from lxml tree. Works in
|
||||
place.'''
|
||||
items = tree.xpath(path)
|
||||
for item in items:
|
||||
item.getparent().remove(item)
|
||||
return tree
|
||||
|
||||
if __name__=='__main__':
|
||||
print xpath('<html><problem name="Bob"></problem></html>', '/{search}/problem[@name="{name}"]', search='html', name="Bob")
|
||||
|
||||
def item(l, default="", process=lambda x:x):
|
||||
if len(l)==0:
|
||||
return default
|
||||
elif len(l)==1:
|
||||
return process(l[0])
|
||||
else:
|
||||
raise Exception('Malformed XML')
|
||||
|
||||
|
||||
def course_file(user):
|
||||
# TODO: Cache. Also, return the libxml2 object.
|
||||
return settings.DATA_DIR+UserProfile.objects.get(user=user).courseware
|
||||
|
||||
def module_xml(coursefile, module, id_tag, module_id):
|
||||
''' Get XML for a module based on module and module_id. Assumes
|
||||
module occurs once in courseware XML file.. '''
|
||||
doc = etree.parse(coursefile)
|
||||
|
||||
# Sanitize input
|
||||
if not module.isalnum():
|
||||
raise Exception("Module is not alphanumeric")
|
||||
if not module_id.isalnum():
|
||||
raise Exception("Module ID is not alphanumeric")
|
||||
xpath_search='//*/{module}[(@{id_tag} = "{id}") or (@id = "{id}")]'.format(module=module,
|
||||
id_tag=id_tag,
|
||||
id=module_id)
|
||||
#result_set=doc.xpathEval(xpath_search)
|
||||
result_set=doc.xpath(xpath_search)
|
||||
if len(result_set)>1:
|
||||
print "WARNING: Potentially malformed course file", module, module_id
|
||||
if len(result_set)==0:
|
||||
return None
|
||||
return etree.tostring(result_set[0])
|
||||
#return result_set[0].serialize()
|
||||
|
||||
def toc_from_xml(coursefile, active_chapter, active_section):
|
||||
dom=parse(coursefile)
|
||||
|
||||
course = dom.getElementsByTagName('course')[0]
|
||||
name=course.getAttribute("name")
|
||||
chapters = course.getElementsByTagName('chapter')
|
||||
ch=list()
|
||||
for c in chapters:
|
||||
if c.getAttribute("name") == 'hidden':
|
||||
continue
|
||||
sections=list()
|
||||
for s in c.getElementsByTagName('section'):
|
||||
sections.append({'name':s.getAttribute("name"),
|
||||
'time':s.getAttribute("time"),
|
||||
'format':s.getAttribute("format"),
|
||||
'due':s.getAttribute("due"),
|
||||
'active':(c.getAttribute("name")==active_chapter and \
|
||||
s.getAttribute("name")==active_section)})
|
||||
ch.append({'name':c.getAttribute("name"),
|
||||
'sections':sections,
|
||||
'active':(c.getAttribute("name")==active_chapter)})
|
||||
return ch
|
||||
|
||||
def dom_select(dom, element_type, element_name):
|
||||
if dom==None:
|
||||
return None
|
||||
elements=dom.getElementsByTagName(element_type)
|
||||
for e in elements:
|
||||
if e.getAttribute("name")==element_name:
|
||||
return e
|
||||
return None
|
||||
|
||||
@@ -17,7 +17,19 @@ class schematic(object):
|
||||
eid = element.get('id')
|
||||
height = element.get('height')
|
||||
width = element.get('width')
|
||||
context = {'id':eid, 'value':value, 'state':state, 'width':width, 'height':height}
|
||||
parts = element.get('parts')
|
||||
analyses = element.get('analyses')
|
||||
initial_value = element.get('initial_value')
|
||||
context = {
|
||||
'id':eid,
|
||||
'value':value,
|
||||
'initial_value':initial_value,
|
||||
'state':state,
|
||||
'width':width,
|
||||
'height':height,
|
||||
'parts':parts,
|
||||
'analyses':analyses,
|
||||
}
|
||||
html=render_to_string("schematicinput.html", context)
|
||||
return etree.XML(html)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import random, numpy, math, scipy
|
||||
import random, numpy, math, scipy, json
|
||||
from util import contextualize_text
|
||||
from calc import evaluator
|
||||
import random, math
|
||||
@@ -63,7 +63,6 @@ class customresponse(object):
|
||||
# be handled by capa_problem
|
||||
return {}
|
||||
|
||||
|
||||
class formularesponse(object):
|
||||
def __init__(self, xml, context):
|
||||
self.xml = xml
|
||||
@@ -114,3 +113,28 @@ class formularesponse(object):
|
||||
|
||||
def get_answers(self):
|
||||
return {self.answer_id:self.correct_answer}
|
||||
|
||||
class schematicresponse(object):
|
||||
def __init__(self, xml, context):
|
||||
self.xml = xml
|
||||
self.answer_ids = xml.xpath('//*[@id=$id]//schematic/@id',
|
||||
id=xml.get('id'))
|
||||
self.context = context
|
||||
answer = xml.xpath('//*[@id=$id]//answer',
|
||||
id=xml.get('id'))[0]
|
||||
answer_src = answer.get('src')
|
||||
if answer_src != None:
|
||||
self.code = open(settings.DATA_DIR+'src/'+answer_src).read()
|
||||
else:
|
||||
self.code = answer.text
|
||||
|
||||
def grade(self, student_answers):
|
||||
submission = [json.loads(student_answers[k]) for k in sorted(self.answer_ids)]
|
||||
self.context.update({'submission':submission})
|
||||
exec self.code in global_context, self.context
|
||||
return zip(sorted(self.answer_ids), self.context['correct'])
|
||||
|
||||
def get_answers(self):
|
||||
# Since this is explicitly specified in the problem, this will
|
||||
# be handled by capa_problem
|
||||
return {}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
from django.conf import settings
|
||||
from xml.dom.minidom import parse, parseString
|
||||
try:
|
||||
from django.conf import settings
|
||||
from auth.models import UserProfile
|
||||
except:
|
||||
settings = None
|
||||
|
||||
from lxml import etree
|
||||
|
||||
from auth.models import UserProfile
|
||||
import json
|
||||
import hashlib
|
||||
|
||||
''' This file will eventually form an abstraction layer between the
|
||||
course XML file and the rest of the system.
|
||||
@@ -11,11 +15,18 @@ course XML file and the rest of the system.
|
||||
TODO: Shift everything from xml.dom.minidom to XPath (or XQuery)
|
||||
'''
|
||||
|
||||
def fasthash(string):
|
||||
m = hashlib.new("md4")
|
||||
m.update(string)
|
||||
return "id"+m.hexdigest()
|
||||
|
||||
def xpath(xml, query_string, **args):
|
||||
''' Safe xpath query into an xml tree:
|
||||
* xml is the tree.
|
||||
* query_string is the query
|
||||
* args are the parameters. Substitute for {params}. '''
|
||||
* args are the parameters. Substitute for {params}.
|
||||
We should remove this with the move to lxml.
|
||||
We should also use lxml argument passing. '''
|
||||
doc = etree.fromstring(xml)
|
||||
print type(doc)
|
||||
def escape(x):
|
||||
@@ -32,8 +43,17 @@ def xpath(xml, query_string, **args):
|
||||
results = doc.xpath(query_string.format(**args))
|
||||
return results
|
||||
|
||||
def xpath_remove(tree, path):
|
||||
''' Remove all items matching path from lxml tree. Works in
|
||||
place.'''
|
||||
items = tree.xpath(path)
|
||||
for item in items:
|
||||
item.getparent().remove(item)
|
||||
return tree
|
||||
|
||||
if __name__=='__main__':
|
||||
print xpath('<html><problem name="Bob"></problem></html>', '/{search}/problem[@name="{name}"]', search='html', name="Bob")
|
||||
print xpath('<html><problem name="Bob"></problem></html>', '/{search}/problem[@name="{name}"]',
|
||||
search='html', name="Bob")
|
||||
|
||||
def item(l, default="", process=lambda x:x):
|
||||
if len(l)==0:
|
||||
@@ -42,16 +62,39 @@ def item(l, default="", process=lambda x:x):
|
||||
return process(l[0])
|
||||
else:
|
||||
raise Exception('Malformed XML')
|
||||
|
||||
def id_tag(course):
|
||||
''' Tag all course elements with unique IDs '''
|
||||
default_ids = {'video':'youtube',
|
||||
'problem':'filename',
|
||||
'sequential':'id',
|
||||
'html':'filename',
|
||||
'vertical':'id',
|
||||
'tab':'id',
|
||||
'schematic':'id'}
|
||||
|
||||
# Tag elements with unique IDs
|
||||
elements = course.xpath("|".join(['//'+c for c in default_ids]))
|
||||
for elem in elements:
|
||||
if elem.get('id'):
|
||||
pass
|
||||
elif elem.get(default_ids[elem.tag]):
|
||||
new_id = elem.get(default_ids[elem.tag]) # Convert to alphanumeric
|
||||
new_id = "".join([a for a in new_id if a.isalnum()])
|
||||
elem.set('id', new_id)
|
||||
else:
|
||||
elem.set('id', fasthash(etree.tostring(elem)))
|
||||
|
||||
def course_file(user):
|
||||
# TODO: Cache. Also, return the libxml2 object.
|
||||
return settings.DATA_DIR+UserProfile.objects.get(user=user).courseware
|
||||
# TODO: Cache.
|
||||
tree = etree.parse(settings.DATA_DIR+UserProfile.objects.get(user=user).courseware)
|
||||
id_tag(tree)
|
||||
return tree
|
||||
|
||||
def module_xml(coursefile, module, id_tag, module_id):
|
||||
''' Get XML for a module based on module and module_id. Assumes
|
||||
module occurs once in courseware XML file.. '''
|
||||
doc = etree.parse(coursefile)
|
||||
doc = coursefile
|
||||
|
||||
# Sanitize input
|
||||
if not module.isalnum():
|
||||
@@ -70,35 +113,24 @@ def module_xml(coursefile, module, id_tag, module_id):
|
||||
return etree.tostring(result_set[0])
|
||||
#return result_set[0].serialize()
|
||||
|
||||
def toc_from_xml(coursefile, active_chapter, active_section):
|
||||
dom=parse(coursefile)
|
||||
def toc_from_xml(dom, active_chapter, active_section):
|
||||
name = dom.xpath('//course/@name')[0]
|
||||
|
||||
course = dom.getElementsByTagName('course')[0]
|
||||
name=course.getAttribute("name")
|
||||
chapters = course.getElementsByTagName('chapter')
|
||||
chapters = dom.xpath('//course[@name=$name]/chapter', name=name)
|
||||
ch=list()
|
||||
for c in chapters:
|
||||
if c.getAttribute("name") == 'hidden':
|
||||
if c.get('name') == 'hidden':
|
||||
continue
|
||||
sections=list()
|
||||
for s in c.getElementsByTagName('section'):
|
||||
sections.append({'name':s.getAttribute("name"),
|
||||
'time':s.getAttribute("time"),
|
||||
'format':s.getAttribute("format"),
|
||||
'due':s.getAttribute("due"),
|
||||
'active':(c.getAttribute("name")==active_chapter and \
|
||||
s.getAttribute("name")==active_section)})
|
||||
ch.append({'name':c.getAttribute("name"),
|
||||
for s in dom.xpath('//course[@name=$name]/chapter[@name=$chname]/section', name=name, chname=c.get('name')):
|
||||
sections.append({'name':s.get("name") or "",
|
||||
'time':s.get("time") or "",
|
||||
'format':s.get("format") or "",
|
||||
'due':s.get("due") or "",
|
||||
'active':(c.get("name")==active_chapter and \
|
||||
s.get("name")==active_section)})
|
||||
ch.append({'name':c.get("name"),
|
||||
'sections':sections,
|
||||
'active':(c.getAttribute("name")==active_chapter)})
|
||||
'active':(c.get("name")==active_chapter)})
|
||||
return ch
|
||||
|
||||
def dom_select(dom, element_type, element_name):
|
||||
if dom==None:
|
||||
return None
|
||||
elements=dom.getElementsByTagName(element_type)
|
||||
for e in elements:
|
||||
if e.getAttribute("name")==element_name:
|
||||
return e
|
||||
return None
|
||||
|
||||
|
||||
@@ -16,10 +16,12 @@ from django.http import Http404
|
||||
|
||||
import urllib
|
||||
|
||||
import capa_module
|
||||
import video_module
|
||||
import html_module
|
||||
import schematic_module
|
||||
import courseware.modules.capa_module
|
||||
import courseware.modules.video_module
|
||||
import courseware.modules.vertical_module
|
||||
import courseware.modules.html_module
|
||||
import courseware.modules.schematic_module
|
||||
import courseware.modules.seq_module
|
||||
|
||||
from models import StudentModule
|
||||
|
||||
@@ -29,12 +31,18 @@ from django.conf import settings
|
||||
|
||||
import content_parser
|
||||
|
||||
import sys
|
||||
|
||||
from lxml import etree
|
||||
import uuid
|
||||
|
||||
modx_modules={'problem':capa_module.LoncapaModule,
|
||||
'video':video_module.VideoModule,
|
||||
'html':html_module.HtmlModule,
|
||||
'schematic':schematic_module.SchematicModule}
|
||||
## TODO: Add registration mechanism
|
||||
modx_modules={'problem':courseware.modules.capa_module.LoncapaModule,
|
||||
'video':courseware.modules.video_module.VideoModule,
|
||||
'html':courseware.modules.html_module.HtmlModule,
|
||||
'vertical':courseware.modules.vertical_module.VerticalModule,
|
||||
'sequential':courseware.modules.seq_module.SequentialModule,
|
||||
'schematic':courseware.modules.schematic_module.SchematicModule}
|
||||
|
||||
def make_track_function(request):
|
||||
def f(event_type, event):
|
||||
@@ -44,11 +52,12 @@ def make_track_function(request):
|
||||
def modx_dispatch(request, module=None, dispatch=None, id=None):
|
||||
''' Generic view for extensions. '''
|
||||
# Grab the student information for the module from the database
|
||||
print module, request.user, id
|
||||
s = StudentModule.objects.filter(module_type=module,
|
||||
student=request.user,
|
||||
module_id=id)
|
||||
if len(s) == 0:
|
||||
print "ls404"
|
||||
print "ls404", module, request.user, id
|
||||
raise Http404
|
||||
|
||||
s=s[0]
|
||||
@@ -67,83 +76,25 @@ def modx_dispatch(request, module=None, dispatch=None, id=None):
|
||||
s.module_id,
|
||||
ajax_url=ajax_url,
|
||||
state=s.state,
|
||||
track_function = make_track_function(request))
|
||||
track_function = make_track_function(request),
|
||||
render_function = render_module,
|
||||
meta = request)
|
||||
# Let the module handle the AJAX
|
||||
ajax_return=instance.handle_ajax(dispatch, request.POST)
|
||||
# Save the state back to the database
|
||||
s.state=instance.get_state()
|
||||
s.grade=instance.get_score()['score']
|
||||
if instance.get_score() != None:
|
||||
s.grade=instance.get_score()['score']
|
||||
s.save()
|
||||
# Return whatever the module wanted to return to the client/caller
|
||||
return HttpResponse(ajax_return)
|
||||
|
||||
def vertical_module(request, module):
|
||||
''' Layout module which lays out content vertically.
|
||||
'''
|
||||
contents=[(e.getAttribute("name"),render_module(request, e)) \
|
||||
for e in module.childNodes \
|
||||
if e.nodeType==1]
|
||||
init_js="".join([e[1]['init_js'] for e in contents if 'init_js' in e[1]])
|
||||
destroy_js="".join([e[1]['destroy_js'] for e in contents if 'destroy_js' in e[1]])
|
||||
|
||||
return {'init_js':init_js,
|
||||
'destroy_js':destroy_js,
|
||||
'content':render_to_string('vert_module.html',{'items':contents}),
|
||||
'type':'vertical'}
|
||||
|
||||
def seq_module(request, module):
|
||||
''' Layout module which lays out content in a temporal sequence
|
||||
'''
|
||||
def j(m):
|
||||
# jsonify contents so it can be embedded in a js array
|
||||
# We also need to split </script> tags so they don't break
|
||||
# mid-string
|
||||
if 'init_js' not in m: m['init_js']=""
|
||||
if 'type' not in m: m['init_js']=""
|
||||
content=json.dumps(m['content'])
|
||||
content=content.replace('</script>', '<"+"/script>')
|
||||
|
||||
return {'content':content,
|
||||
"destroy_js":m['destroy_js'],
|
||||
'init_js':m['init_js'],
|
||||
'type':m['type']}
|
||||
contents=[(e.getAttribute("name"),j(render_module(request, e))) \
|
||||
for e in module.childNodes \
|
||||
if e.nodeType==1]
|
||||
|
||||
js=""
|
||||
|
||||
iid=uuid.uuid1().hex
|
||||
|
||||
params={'items':contents,
|
||||
'id':"seq"}
|
||||
|
||||
# TODO/BUG: Destroy JavaScript should only be called for the active view
|
||||
# This calls it for all the views
|
||||
#
|
||||
# To fix this, we'd probably want to have some way of assigning unique
|
||||
# IDs to sequences.
|
||||
destroy_js="".join([e[1]['destroy_js'] for e in contents if 'destroy_js' in e[1]])
|
||||
|
||||
if module.nodeName == 'sequential':
|
||||
return {'init_js':js+render_to_string('seq_module.js',params),
|
||||
"destroy_js":destroy_js,
|
||||
'content':render_to_string('seq_module.html',params),
|
||||
'type':'sequential'}
|
||||
if module.nodeName == 'tab':
|
||||
params['id'] = 'tab'
|
||||
return {'init_js':js+render_to_string('tab_module.js',params),
|
||||
"destroy_js":destroy_js,
|
||||
'content':render_to_string('tab_module.html',params),
|
||||
'type':'tab'}
|
||||
|
||||
|
||||
def render_x_module(request, xml_module):
|
||||
''' Generic module for extensions. This renders to HTML. '''
|
||||
# Check if problem has an instance in DB
|
||||
module_type=xml_module.nodeName
|
||||
module_type=xml_module.tag
|
||||
module_class=modx_modules[module_type]
|
||||
module_id=xml_module.getAttribute(module_class.id_attribute)
|
||||
module_id=xml_module.get('id') #module_class.id_attribute) or ""
|
||||
|
||||
# Grab state from database
|
||||
s = StudentModule.objects.filter(student=request.user,
|
||||
@@ -157,11 +108,13 @@ def render_x_module(request, xml_module):
|
||||
|
||||
# Create a new instance
|
||||
ajax_url = '/modx/'+module_type+'/'+module_id+'/'
|
||||
instance=module_class(xml_module.toxml(),
|
||||
instance=module_class(etree.tostring(xml_module),
|
||||
module_id,
|
||||
ajax_url=ajax_url,
|
||||
state=state,
|
||||
track_function = make_track_function(request))
|
||||
track_function = make_track_function(request),
|
||||
render_function = render_module,
|
||||
meta = request)
|
||||
|
||||
# If instance wasn't already in the database, create it
|
||||
if len(s) == 0:
|
||||
@@ -179,20 +132,8 @@ def render_x_module(request, xml_module):
|
||||
|
||||
return content
|
||||
|
||||
module_types={'video':render_x_module,
|
||||
'html':render_x_module,
|
||||
'tab':seq_module,
|
||||
'vertical':vertical_module,
|
||||
'sequential':seq_module,
|
||||
'problem':render_x_module,
|
||||
'schematic':render_x_module
|
||||
}
|
||||
|
||||
def render_module(request, module):
|
||||
''' Generic dispatch for internal modules. '''
|
||||
if module==None:
|
||||
if module==None :
|
||||
return {"content":""}
|
||||
if str(module.localName) in module_types:
|
||||
return module_types[module.localName](request, module)
|
||||
print "rm404"
|
||||
raise Http404
|
||||
return render_x_module(request, module)
|
||||
|
||||
0
courseware/modules/__init__.py
Normal file
0
courseware/modules/__init__.py
Normal file
@@ -2,14 +2,14 @@ import random, numpy, math, scipy, sys, StringIO, os, struct, json
|
||||
from x_module import XModule
|
||||
import sys
|
||||
|
||||
from capa.capa_problem import LoncapaProblem
|
||||
from courseware.capa.capa_problem import LoncapaProblem
|
||||
from django.http import Http404
|
||||
|
||||
import dateutil
|
||||
import dateutil.parser
|
||||
import datetime
|
||||
|
||||
import content_parser
|
||||
import courseware.content_parser as content_parser
|
||||
|
||||
from lxml import etree
|
||||
|
||||
@@ -108,8 +108,8 @@ class LoncapaModule(XModule):
|
||||
|
||||
return html
|
||||
|
||||
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None):
|
||||
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function)
|
||||
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None, render_function = None, meta = None):
|
||||
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function, render_function)
|
||||
|
||||
self.attempts = 0
|
||||
self.max_attempts = None
|
||||
@@ -25,8 +25,8 @@ class HtmlModule(XModule):
|
||||
textlist=[i for i in textlist if type(i)==str]
|
||||
return "".join(textlist)
|
||||
|
||||
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None):
|
||||
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function)
|
||||
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None, render_function = None, meta = None):
|
||||
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function, render_function)
|
||||
xmltree=etree.fromstring(xml)
|
||||
self.filename = None
|
||||
filename_l=xmltree.xpath("/html/@filename")
|
||||
@@ -18,6 +18,6 @@ class SchematicModule(XModule):
|
||||
def get_html(self):
|
||||
return '<input type="hidden" class="schematic" name="{item_id}" height="480" width="640">'.format(item_id=self.item_id)
|
||||
|
||||
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None):
|
||||
XModule.__init__(self, xml, item_id, ajax_url, track_url, state)
|
||||
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, render_function = None, meta = None):
|
||||
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, render_function)
|
||||
|
||||
87
courseware/modules/seq_module.py
Normal file
87
courseware/modules/seq_module.py
Normal file
@@ -0,0 +1,87 @@
|
||||
from x_module import XModule
|
||||
from lxml import etree
|
||||
from django.http import Http404
|
||||
|
||||
import json
|
||||
|
||||
## TODO: Abstract out from Django
|
||||
from django.conf import settings
|
||||
from djangomako.shortcuts import render_to_response, render_to_string
|
||||
|
||||
class SequentialModule(XModule):
|
||||
''' Layout module which lays out content in a temporal sequence
|
||||
'''
|
||||
id_attribute = 'id'
|
||||
|
||||
def get_state(self):
|
||||
return json.dumps({ 'position':self.position })
|
||||
|
||||
def get_xml_tags():
|
||||
return ["sequential", 'tab']
|
||||
|
||||
def get_html(self):
|
||||
return self.content
|
||||
|
||||
def get_init_js(self):
|
||||
return self.init_js
|
||||
|
||||
def get_destroy_js(self):
|
||||
return self.destroy_js
|
||||
|
||||
def handle_ajax(self, dispatch, get):
|
||||
print "GET", get
|
||||
print "DISPATCH", dispatch
|
||||
if dispatch=='goto_position':
|
||||
self.position = int(get['position'])
|
||||
return json.dumps({'success':True})
|
||||
raise Http404()
|
||||
|
||||
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None, render_function = None, meta = None):
|
||||
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function, render_function)
|
||||
xmltree=etree.fromstring(xml)
|
||||
|
||||
self.position = 1
|
||||
|
||||
if state!=None:
|
||||
state = json.loads(state)
|
||||
if 'position' in state: self.position = int(state['position'])
|
||||
|
||||
def j(m):
|
||||
''' jsonify contents so it can be embedded in a js array
|
||||
We also need to split </script> tags so they don't break
|
||||
mid-string'''
|
||||
if 'init_js' not in m: m['init_js']=""
|
||||
if 'type' not in m: m['init_js']=""
|
||||
content=json.dumps(m['content'])
|
||||
content=content.replace('</script>', '<"+"/script>')
|
||||
|
||||
return {'content':content,
|
||||
"destroy_js":m['destroy_js'],
|
||||
'init_js':m['init_js'],
|
||||
'type':m['type']}
|
||||
|
||||
contents=[(e.get("name"),j(render_function(meta, e))) \
|
||||
for e in xmltree]
|
||||
|
||||
js=""
|
||||
|
||||
params={'items':contents,
|
||||
'id':item_id,
|
||||
'position': self.position}
|
||||
|
||||
# TODO/BUG: Destroy JavaScript should only be called for the active view
|
||||
# This calls it for all the views
|
||||
#
|
||||
# To fix this, we'd probably want to have some way of assigning unique
|
||||
# IDs to sequences.
|
||||
destroy_js="".join([e[1]['destroy_js'] for e in contents if 'destroy_js' in e[1]])
|
||||
|
||||
if xmltree.tag == 'sequential':
|
||||
self.init_js=js+render_to_string('seq_module.js',params)
|
||||
self.destroy_js=destroy_js
|
||||
self.content=render_to_string('seq_module.html',params)
|
||||
if xmltree.tag == 'tab':
|
||||
params['id'] = 'tab'
|
||||
self.init_js=js+render_to_string('tab_module.js',params)
|
||||
self.destroy_js=destroy_js
|
||||
self.content=render_to_string('tab_module.html',params)
|
||||
34
courseware/modules/vertical_module.py
Normal file
34
courseware/modules/vertical_module.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from x_module import XModule
|
||||
from lxml import etree
|
||||
|
||||
import json
|
||||
|
||||
## TODO: Abstract out from Django
|
||||
from django.conf import settings
|
||||
from djangomako.shortcuts import render_to_response, render_to_string
|
||||
|
||||
class VerticalModule(XModule):
|
||||
id_attribute = 'id'
|
||||
|
||||
def get_state(self):
|
||||
return json.dumps({ })
|
||||
|
||||
def get_xml_tags():
|
||||
return "vertical"
|
||||
|
||||
def get_html(self):
|
||||
return render_to_string('vert_module.html',{'items':self.contents})
|
||||
|
||||
def get_init_js(self):
|
||||
return self.init_js_text
|
||||
|
||||
def get_destroy_js(self):
|
||||
return self.destroy_js_text
|
||||
|
||||
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None, render_function = None, meta = None):
|
||||
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function, render_function)
|
||||
xmltree=etree.fromstring(xml)
|
||||
self.contents=[(e.get("name"),self.render_function(meta, e)) \
|
||||
for e in xmltree]
|
||||
self.init_js_text="".join([e[1]['init_js'] for e in self.contents if 'init_js' in e[1]])
|
||||
self.destroy_js_text="".join([e[1]['destroy_js'] for e in self.contents if 'destroy_js' in e[1]])
|
||||
@@ -1,4 +1,5 @@
|
||||
from x_module import XModule
|
||||
from lxml import etree
|
||||
|
||||
import json
|
||||
|
||||
@@ -7,47 +8,55 @@ from django.conf import settings
|
||||
from djangomako.shortcuts import render_to_response, render_to_string
|
||||
|
||||
class VideoModule(XModule):
|
||||
id_attribute = 'youtube'
|
||||
#id_attribute = 'youtube'
|
||||
video_time = 0
|
||||
|
||||
def handle_ajax(self, dispatch, get):
|
||||
if dispatch == 'time':
|
||||
self.video_time = int(get['time'])
|
||||
print self.video_time
|
||||
|
||||
return json.dumps("True")
|
||||
print "GET", get
|
||||
print "DISPATCH", dispatch
|
||||
if dispatch=='goto_position':
|
||||
self.position = int(float(get['position']))
|
||||
print "NEW POSITION", self.position
|
||||
return json.dumps({'success':True})
|
||||
raise Http404()
|
||||
|
||||
def get_state(self):
|
||||
return json.dumps({ 'time':self.video_time })
|
||||
print "STATE POSITION", self.position
|
||||
return json.dumps({ 'position':self.position })
|
||||
|
||||
def get_xml_tags():
|
||||
''' Tags in the courseware file guaranteed to correspond to the module '''
|
||||
return "video"
|
||||
|
||||
def video_list(self):
|
||||
l=self.item_id.split(',')
|
||||
l=self.youtube.split(',')
|
||||
l=[i.split(":") for i in l]
|
||||
return json.dumps(dict(l))
|
||||
|
||||
def get_html(self):
|
||||
return render_to_string('video.html',{'streams':self.video_list(),
|
||||
'id':self.item_id,
|
||||
'video_time':self.video_time})
|
||||
'position':self.position})
|
||||
|
||||
def get_init_js(self):
|
||||
''' JavaScript code to be run when problem is shown. Be aware
|
||||
that this may happen several times on the same page
|
||||
(e.g. student switching tabs). Common functions should be put
|
||||
in the main course .js files for now. '''
|
||||
print "INIT POSITION", self.position
|
||||
return render_to_string('video_init.js',{'streams':self.video_list(),
|
||||
'id':self.item_id,
|
||||
'video_time':self.video_time})
|
||||
'position':self.position})
|
||||
|
||||
def get_destroy_js(self):
|
||||
return "videoDestroy();"
|
||||
return "videoDestroy(\""+self.item_id+"\");"
|
||||
|
||||
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None):
|
||||
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function)
|
||||
print state
|
||||
if state!=None and "time" not in json.loads(state):
|
||||
self.video_time = 0
|
||||
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None, render_function = None, meta = None):
|
||||
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function, render_function)
|
||||
self.youtube = etree.XML(xml).get('youtube')
|
||||
self.position = 0
|
||||
if state!=None:
|
||||
state = json.loads(state)
|
||||
if 'position' in state: self.position = int(float(state['position']))
|
||||
print "POOSITION IN STATE"
|
||||
print "LOAD POSITION", self.position
|
||||
@@ -39,11 +39,13 @@ class XModule(object):
|
||||
get is a dictionary-like object '''
|
||||
return ""
|
||||
|
||||
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None):
|
||||
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None, render_function = None, meta = None):
|
||||
''' In most cases, you must pass state or xml'''
|
||||
self.xml=xml
|
||||
self.item_id=item_id
|
||||
self.ajax_url=ajax_url
|
||||
self.track_url=track_url
|
||||
self.state=state
|
||||
self.tracker=track_function
|
||||
self.xml = xml
|
||||
self.item_id = item_id
|
||||
self.ajax_url = ajax_url
|
||||
self.track_url = track_url
|
||||
self.state = state
|
||||
self.tracker = track_function
|
||||
self.render_function = render_function
|
||||
self.meta = meta
|
||||
@@ -1,7 +1,6 @@
|
||||
from django.http import HttpResponse
|
||||
from django.template import Context, loader
|
||||
from djangomako.shortcuts import render_to_response, render_to_string
|
||||
from xml.dom.minidom import parse, parseString
|
||||
import json, os, sys
|
||||
from django.core.context_processors import csrf
|
||||
|
||||
@@ -14,11 +13,6 @@ import StringIO
|
||||
|
||||
from django.http import Http404
|
||||
|
||||
import urllib
|
||||
|
||||
import capa_module
|
||||
import video_module
|
||||
|
||||
from models import StudentModule
|
||||
|
||||
import urllib
|
||||
@@ -31,6 +25,11 @@ import uuid
|
||||
|
||||
from module_render import *
|
||||
|
||||
from lxml import etree
|
||||
|
||||
etree.set_default_parser(etree.XMLParser(dtd_validation=False, load_dtd=False,
|
||||
remove_comments = True))
|
||||
|
||||
template_imports={'urllib':urllib}
|
||||
|
||||
def profile(request):
|
||||
@@ -39,20 +38,23 @@ def profile(request):
|
||||
if not request.user.is_authenticated():
|
||||
return redirect('/')
|
||||
|
||||
dom=parse(content_parser.course_file(request.user))
|
||||
dom=content_parser.course_file(request.user)
|
||||
hw=[]
|
||||
course = dom.getElementsByTagName('course')[0]
|
||||
chapters = course.getElementsByTagName('chapter')
|
||||
course = dom.xpath('//course/@name')[0]
|
||||
chapters = dom.xpath('//course[@name=$course]/chapter', course=course)
|
||||
|
||||
responses=StudentModule.objects.filter(student=request.user)
|
||||
|
||||
for c in chapters:
|
||||
for s in c.getElementsByTagName('section'):
|
||||
problems=s.getElementsByTagName('problem')
|
||||
chname=c.get('name')
|
||||
for s in dom.xpath('//course[@name=$course]/chapter[@name=$chname]/section',
|
||||
course=course, chname=chname):
|
||||
problems=dom.xpath('//course[@name=$course]/chapter[@name=$chname]/section[@name=$section]//problem',
|
||||
course=course, chname=chname, section=s.get('name'))
|
||||
scores=[]
|
||||
if len(problems)>0:
|
||||
for p in problems:
|
||||
id = p.getAttribute('filename')
|
||||
id = p.get('filename')
|
||||
correct = 0
|
||||
for response in responses:
|
||||
if response.module_id == id:
|
||||
@@ -60,11 +62,11 @@ def profile(request):
|
||||
correct=response.grade
|
||||
else:
|
||||
correct=0
|
||||
total=capa_module.LoncapaModule(p.toxml(), "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))
|
||||
score={'course':course.getAttribute('name'),
|
||||
'section':s.getAttribute("name"),
|
||||
'chapter':c.getAttribute("name"),
|
||||
score={'course':course,
|
||||
'section':s.get("name"),
|
||||
'chapter':c.get("name"),
|
||||
'scores':scores,
|
||||
}
|
||||
hw.append(score)
|
||||
@@ -109,6 +111,7 @@ def index(request, course="6.002 Spring 2012", chapter="Using the System", secti
|
||||
|
||||
# Fixes URLs -- we don't get funny encoding characters from spaces
|
||||
# so they remain readable
|
||||
## TODO: Properly replace underscores
|
||||
course=course.replace("_"," ")
|
||||
chapter=chapter.replace("_"," ")
|
||||
section=section.replace("_"," ")
|
||||
@@ -118,15 +121,13 @@ def index(request, course="6.002 Spring 2012", chapter="Using the System", secti
|
||||
if course!="6.002 Spring 2012":
|
||||
return redirect('/')
|
||||
|
||||
cf = content_parser.course_file(request.user)
|
||||
dom=parse(cf)
|
||||
dom_course=content_parser.dom_select(dom, 'course', course)
|
||||
dom_chapter=content_parser.dom_select(dom_course, 'chapter', chapter)
|
||||
dom_section=content_parser.dom_select(dom_chapter, 'section', section)
|
||||
if dom_section!=None:
|
||||
module=[e for e in dom_section.childNodes if e.nodeType==1][0]
|
||||
dom = content_parser.course_file(request.user)
|
||||
dom_module = dom.xpath("//course[@name=$course]/chapter[@name=$chapter]//section[@name=$section]/*[1]",
|
||||
course=course, chapter=chapter, section=section)
|
||||
if len(dom_module) == 0:
|
||||
module = None
|
||||
else:
|
||||
module=None
|
||||
module = dom_module[0]
|
||||
|
||||
accordion=render_accordion(request, course, chapter, section)
|
||||
|
||||
@@ -135,6 +136,8 @@ def index(request, course="6.002 Spring 2012", chapter="Using the System", secti
|
||||
if 'init_js' not in module:
|
||||
module['init_js']=''
|
||||
|
||||
|
||||
|
||||
context={'init':accordion['init_js']+module['init_js'],
|
||||
'accordion':accordion['content'],
|
||||
'content':module['content'],
|
||||
|
||||
@@ -1,256 +0,0 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
import djcelery
|
||||
|
||||
COURSEWARE_ENABLED = True
|
||||
ASKBOT_ENABLED = True
|
||||
|
||||
CSRF_COOKIE_DOMAIN = '127.0.0.1'
|
||||
|
||||
# Defaults to be overridden
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||
SITE_NAME = "localhost:8000"
|
||||
|
||||
DEFAULT_FROM_EMAIL = 'registration@mitx.mit.edu'
|
||||
DEFAULT_FEEDBACK_EMAIL = 'feedback@mitx.mit.edu'
|
||||
|
||||
GENERATE_RANDOM_USER_CREDENTIALS = False
|
||||
|
||||
WIKI_REQUIRE_LOGIN_EDIT = True
|
||||
WIKI_REQUIRE_LOGIN_VIEW = True
|
||||
|
||||
PERFSTATS = False
|
||||
|
||||
HTTPS = 'on'
|
||||
|
||||
MEDIA_URL = ''
|
||||
MEDIA_ROOT = ''
|
||||
|
||||
DEBUG = True
|
||||
TEMPLATE_DEBUG = DEBUG
|
||||
|
||||
ADMINS = (
|
||||
('Piotr Mitros', 'pmitros@csail.mit.edu'),
|
||||
)
|
||||
|
||||
MANAGERS = ADMINS
|
||||
|
||||
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
||||
TIME_ZONE = 'America/Chicago'
|
||||
|
||||
# Language code for this installation. All choices can be found here:
|
||||
# http://www.i18nguy.com/unicode/language-identifiers.html
|
||||
LANGUAGE_CODE = 'en'
|
||||
|
||||
SITE_ID = 1
|
||||
|
||||
# If you set this to False, Django will make some optimizations so as not
|
||||
# to load the internationalization machinery.
|
||||
USE_I18N = True
|
||||
|
||||
# If you set this to False, Django will not format dates, numbers and
|
||||
# calendars according to the current locale
|
||||
USE_L10N = True
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
# URL prefix for admin static files -- CSS, JavaScript and images.
|
||||
# Make sure to use a trailing slash.
|
||||
# Examples: "http://foo.com/static/admin/", "/static/admin/".
|
||||
ADMIN_MEDIA_PREFIX = '/static/admin/'
|
||||
|
||||
# List of finder classes that know how to find static files in
|
||||
# various locations.
|
||||
STATICFILES_FINDERS = (
|
||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
|
||||
)
|
||||
|
||||
# List of callables that know how to import templates from various sources.
|
||||
TEMPLATE_LOADERS = (
|
||||
'django.template.loaders.filesystem.Loader',
|
||||
'django.template.loaders.app_directories.Loader',
|
||||
# 'django.template.loaders.eggs.Loader',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'track.middleware.TrackMiddleware',
|
||||
'djangomako.middleware.MakoMiddleware',
|
||||
#'debug_toolbar.middleware.DebugToolbarMiddleware',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = 'mitx.urls'
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'courseware',
|
||||
'auth',
|
||||
'django.contrib.humanize',
|
||||
'static_template_view',
|
||||
'staticbook',
|
||||
'simplewiki',
|
||||
'track',
|
||||
'circuit',
|
||||
'perfstats',
|
||||
# Uncomment the next line to enable the admin:
|
||||
# 'django.contrib.admin',
|
||||
# Uncomment the next line to enable admin documentation:
|
||||
# 'django.contrib.admindocs',
|
||||
)
|
||||
|
||||
# A sample logging configuration. The only tangible logging
|
||||
# performed by this configuration is to send an email to
|
||||
# the site admins on every HTTP 500 error.
|
||||
# See http://docs.djangoproject.com/en/dev/topics/logging for
|
||||
# more details on how to customize your logging configuration.
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'handlers': {
|
||||
'mail_admins': {
|
||||
'level': 'ERROR',
|
||||
'class': 'django.utils.log.AdminEmailHandler'
|
||||
}
|
||||
},
|
||||
'loggers': {
|
||||
'django.request': {
|
||||
'handlers': ['mail_admins'],
|
||||
'level': 'ERROR',
|
||||
'propagate': True,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#TRACK_DIR = None
|
||||
DEBUG_TRACK_LOG = False
|
||||
# Maximum length of a tracking string. We don't want e.g. a file upload in our log
|
||||
TRACK_MAX_EVENT = 1000
|
||||
# Maximum length of log file before starting a new one.
|
||||
MAXLOG = 500
|
||||
|
||||
# Our parent dir (mitx_all) is the BASE_DIR
|
||||
BASE_DIR = os.path.abspath(os.path.join(__file__, "..", ".."))
|
||||
|
||||
# Make sure we execute correctly regardless of where we're called from
|
||||
execfile(os.path.join(BASE_DIR, "settings.py"))
|
||||
|
||||
|
||||
if PERFSTATS :
|
||||
MIDDLEWARE_CLASSES = ( 'perfstats.middleware.ProfileMiddleware',) + MIDDLEWARE_CLASSES
|
||||
|
||||
if 'TRACK_DIR' not in locals():
|
||||
TRACK_DIR = BASE_DIR+'/track_dir/'
|
||||
if 'STATIC_ROOT' not in locals():
|
||||
STATIC_ROOT = BASE_DIR+'/staticroot/'
|
||||
if 'DATA_DIR' not in locals():
|
||||
DATA_DIR = BASE_DIR+'/data/'
|
||||
if 'TEXTBOOK_DIR' not in locals():
|
||||
TEXTBOOK_DIR = BASE_DIR+'/textbook/'
|
||||
|
||||
if 'TEMPLATE_DIRS' not in locals():
|
||||
TEMPLATE_DIRS = (
|
||||
BASE_DIR+'/templates/',
|
||||
DATA_DIR+'/templates',
|
||||
TEXTBOOK_DIR,
|
||||
)
|
||||
|
||||
if 'STATICFILES_DIRS' not in locals():
|
||||
STATICFILES_DIRS = (
|
||||
BASE_DIR+'/3rdParty/static',
|
||||
BASE_DIR+'/static',
|
||||
)
|
||||
|
||||
if 'ASKBOT_EXTRA_SKINS_DIR' not in locals():
|
||||
ASKBOT_EXTRA_SKINS_DIR = BASE_DIR+'/askbot-devel/askbot/skins'
|
||||
if 'ASKBOT_DIR' not in locals():
|
||||
ASKBOT_DIR = BASE_DIR+'/askbot-devel'
|
||||
|
||||
sys.path.append(ASKBOT_DIR)
|
||||
import askbot
|
||||
import site
|
||||
|
||||
STATICFILES_DIRS = STATICFILES_DIRS + ( ASKBOT_DIR+'/askbot/skins',)
|
||||
|
||||
# Needed for Askbot
|
||||
# Critical TODO: Move to S3
|
||||
MEDIA_URL = '/discussion/upfiles/'
|
||||
MEDIA_ROOT = ASKBOT_DIR+'/askbot/upfiles'
|
||||
|
||||
ASKBOT_ROOT = os.path.dirname(askbot.__file__)
|
||||
|
||||
site.addsitedir(os.path.join(os.path.dirname(askbot.__file__), 'deps'))
|
||||
TEMPLATE_LOADERS = TEMPLATE_LOADERS + ('askbot.skins.loaders.filesystem_load_template_source',)
|
||||
|
||||
MIDDLEWARE_CLASSES = MIDDLEWARE_CLASSES + (
|
||||
'askbot.middleware.anon_user.ConnectToSessionMessagesMiddleware',
|
||||
'askbot.middleware.forum_mode.ForumModeMiddleware',
|
||||
'askbot.middleware.cancel.CancelActionMiddleware',
|
||||
'django.middleware.transaction.TransactionMiddleware',
|
||||
#'debug_toolbar.middleware.DebugToolbarMiddleware',
|
||||
'askbot.middleware.view_log.ViewLogMiddleware',
|
||||
'askbot.middleware.spaceless.SpacelessMiddleware',
|
||||
# 'askbot.middleware.pagesize.QuestionsPageSizeMiddleware',
|
||||
)
|
||||
|
||||
FILE_UPLOAD_TEMP_DIR = os.path.join(os.path.dirname(__file__), 'tmp').replace('\\','/')
|
||||
FILE_UPLOAD_HANDLERS = (
|
||||
'django.core.files.uploadhandler.MemoryFileUploadHandler',
|
||||
'django.core.files.uploadhandler.TemporaryFileUploadHandler',
|
||||
)
|
||||
ASKBOT_ALLOWED_UPLOAD_FILE_TYPES = ('.jpg', '.jpeg', '.gif', '.bmp', '.png', '.tiff')
|
||||
ASKBOT_MAX_UPLOAD_FILE_SIZE = 1024 * 1024 #result in bytes
|
||||
# ASKBOT_FILE_UPLOAD_DIR = os.path.join(os.path.dirname(__file__), 'askbot', 'upfiles')
|
||||
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
|
||||
|
||||
PROJECT_ROOT = os.path.dirname(__file__)
|
||||
|
||||
TEMPLATE_CONTEXT_PROCESSORS = (
|
||||
'django.core.context_processors.request',
|
||||
'askbot.context.application_settings',
|
||||
#'django.core.context_processors.i18n',
|
||||
'askbot.user_messages.context_processors.user_messages',#must be before auth
|
||||
'django.core.context_processors.auth', #this is required for admin
|
||||
'django.core.context_processors.csrf', #necessary for csrf protection
|
||||
)
|
||||
|
||||
INSTALLED_APPS = INSTALLED_APPS + (
|
||||
'django.contrib.sitemaps',
|
||||
'django.contrib.admin',
|
||||
'south',
|
||||
'askbot.deps.livesettings',
|
||||
'askbot',
|
||||
#'keyedcache', # TODO: Main askbot tree has this installed, but we get intermittent errors if we include it.
|
||||
'robots',
|
||||
'django_countries',
|
||||
'djcelery',
|
||||
'djkombu',
|
||||
'followit',
|
||||
)
|
||||
|
||||
CACHE_MIDDLEWARE_ANONYMOUS_ONLY = True
|
||||
ASKBOT_URL = 'discussion/'
|
||||
LOGIN_REDIRECT_URL = '/'
|
||||
LOGIN_URL = '/'
|
||||
|
||||
# ASKBOT_UPLOADED_FILES_URL = '%s%s' % (ASKBOT_URL, 'upfiles/')
|
||||
ALLOW_UNICODE_SLUGS = False
|
||||
ASKBOT_USE_STACKEXCHANGE_URLS = False #mimic url scheme of stackexchange
|
||||
ASKBOT_CSS_DEVEL = True
|
||||
|
||||
# Celery Settings
|
||||
BROKER_TRANSPORT = "djkombu.transport.DatabaseTransport"
|
||||
CELERY_ALWAYS_EAGER = True
|
||||
|
||||
djcelery.setup_loader()
|
||||
1
settings_new_askbot.py
Symbolic link
1
settings_new_askbot.py
Symbolic link
@@ -0,0 +1 @@
|
||||
settings_old_askbot.py
|
||||
@@ -48,7 +48,7 @@ def root_redirect(request):
|
||||
try:
|
||||
root = Article.get_root()
|
||||
except:
|
||||
err = not_found(request, 'mainpage')
|
||||
err = not_found(request, '/')
|
||||
return err
|
||||
|
||||
return HttpResponseRedirect(reverse('wiki_view', args=(root.get_url())))
|
||||
@@ -92,7 +92,7 @@ def create(request, wiki_url):
|
||||
#except ShouldHaveExactlyOneRootSlug, (e):
|
||||
except:
|
||||
if Article.objects.filter(parent=None).count() > 0:
|
||||
return HttpResponseRedirect(reverse('wiki_view', args=('',)))
|
||||
return HttpResponseRedirect(reverse('wiki_view', args=('/',)))
|
||||
# Root not found...
|
||||
path = []
|
||||
url_path = [""]
|
||||
@@ -380,7 +380,7 @@ def fetch_from_url(request, url):
|
||||
try:
|
||||
root = Article.get_root()
|
||||
except:
|
||||
err = not_found(request, '')
|
||||
err = not_found(request, '/')
|
||||
return (article, path, err)
|
||||
|
||||
if url_path and root.slug == url_path[0]:
|
||||
|
||||
@@ -8,7 +8,12 @@ from django.shortcuts import redirect
|
||||
from django.core.context_processors import csrf
|
||||
|
||||
#valid_templates=['index.html', 'staff.html', 'info.html', 'credits.html']
|
||||
valid_templates=['mitx_global.html', 'index.html']
|
||||
valid_templates=['mitx_global.html',
|
||||
'index.html',
|
||||
'tos.html',
|
||||
'privacy.html',
|
||||
'honor.html',
|
||||
'copyright.html']
|
||||
|
||||
def index(request, template):
|
||||
csrf_token = csrf(request)['csrf_token']
|
||||
|
||||
Reference in New Issue
Block a user