Commit fc54b001 by Bridger Maxwell

Added a start date to courses. Created a decorator to retrieve the course and…

Added a start date to courses. Created a decorator to retrieve the course and check that it is open.
parent a56658fd
from datetime import datetime
import dateutil.parser
from fs.errors import ResourceNotFoundError from fs.errors import ResourceNotFoundError
import logging import logging
from path import path from path import path
...@@ -13,6 +15,14 @@ log = logging.getLogger(__name__) ...@@ -13,6 +15,14 @@ log = logging.getLogger(__name__)
class CourseDescriptor(SequenceDescriptor): class CourseDescriptor(SequenceDescriptor):
module_class = SequenceModule module_class = SequenceModule
def __init__(self, system, definition=None, **kwargs):
super(CourseDescriptor, self).__init__(system, definition, **kwargs)
self.start = dateutil.parser.parse(self.metadata["start"])
def has_started(self):
return datetime.now() > self.start
@classmethod @classmethod
def id_to_location(cls, course_id): def id_to_location(cls, course_id):
org, course, name = course_id.split('/') org, course, name = course_id.split('/')
...@@ -24,7 +34,7 @@ class CourseDescriptor(SequenceDescriptor): ...@@ -24,7 +34,7 @@ class CourseDescriptor(SequenceDescriptor):
@property @property
def title(self): def title(self):
self.metadata['display_name'] return self.metadata['display_name']
@property @property
def instructors(self): def instructors(self):
...@@ -69,6 +79,7 @@ class CourseDescriptor(SequenceDescriptor): ...@@ -69,6 +79,7 @@ class CourseDescriptor(SequenceDescriptor):
elif section_key == "title": elif section_key == "title":
return self.metadata.get('display_name', self.name) return self.metadata.get('display_name', self.name)
elif section_key == "university": elif section_key == "university":
return self.metadata.get('start')
return self.location.org return self.location.org
elif section_key == "number": elif section_key == "number":
return self.number return self.number
......
...@@ -214,7 +214,7 @@ class XModuleDescriptor(Plugin): ...@@ -214,7 +214,7 @@ class XModuleDescriptor(Plugin):
# A list of metadata that this module can inherit from its parent module # A list of metadata that this module can inherit from its parent module
inheritable_metadata = ( inheritable_metadata = (
'graded', 'due', 'graceperiod', 'showanswer', 'rerandomize', 'graded', 'start', 'due', 'graceperiod', 'showanswer', 'rerandomize',
# This is used by the XMLModuleStore to provide for locations for static files, # This is used by the XMLModuleStore to provide for locations for static files,
# and will need to be removed when that code is removed # and will need to be removed when that code is removed
...@@ -251,6 +251,7 @@ class XModuleDescriptor(Plugin): ...@@ -251,6 +251,7 @@ class XModuleDescriptor(Plugin):
display_name: The name to use for displaying this module to the user display_name: The name to use for displaying this module to the user
format: The format of this module ('Homework', 'Lab', etc) format: The format of this module ('Homework', 'Lab', etc)
graded (bool): Whether this module is should be graded or not graded (bool): Whether this module is should be graded or not
start (string): The date for which this module will be available
due (string): The due date for this module due (string): The due date for this module
graceperiod (string): The amount of grace period to allow when enforcing the due date graceperiod (string): The amount of grace period to allow when enforcing the due date
showanswer (string): When to show answers for this module showanswer (string): When to show answers for this module
......
...@@ -88,7 +88,7 @@ class XmlDescriptor(XModuleDescriptor): ...@@ -88,7 +88,7 @@ class XmlDescriptor(XModuleDescriptor):
# The attributes will be removed from the definition xml passed # The attributes will be removed from the definition xml passed
# to definition_from_xml, and from the xml returned by definition_to_xml # to definition_from_xml, and from the xml returned by definition_to_xml
metadata_attributes = ('format', 'graceperiod', 'showanswer', 'rerandomize', metadata_attributes = ('format', 'graceperiod', 'showanswer', 'rerandomize',
'due', 'graded', 'name', 'slug') 'start', 'due', 'graded', 'name', 'slug')
# A dictionary mapping xml attribute names to functions of the value # A dictionary mapping xml attribute names to functions of the value
# that return the metadata key and value # that return the metadata key and value
......
...@@ -27,6 +27,25 @@ log = logging.getLogger("mitx.courseware") ...@@ -27,6 +27,25 @@ log = logging.getLogger("mitx.courseware")
template_imports = {'urllib': urllib} template_imports = {'urllib': urllib}
def check_course(function, course_must_be_open=True):
def inner_function(*args, **kwargs):
course_id = kwargs['course_id']
try:
course_loc = CourseDescriptor.id_to_location(course_id)
course = modulestore().get_item(course_loc)
except KeyError:
raise Http404("Course not found.")
if course_must_be_open and not course.has_started():
raise Http404
del kwargs['course_id']
kwargs['course'] = course
return function(*args, **kwargs)
return inner_function
def user_groups(user): def user_groups(user):
if not user.is_authenticated(): if not user.is_authenticated():
...@@ -84,12 +103,12 @@ def gradebook(request, course_id): ...@@ -84,12 +103,12 @@ def gradebook(request, course_id):
@login_required @login_required
@check_course
@cache_control(no_cache=True, no_store=True, must_revalidate=True) @cache_control(no_cache=True, no_store=True, must_revalidate=True)
def profile(request, course_id, student_id=None): def profile(request, course, student_id=None):
''' User profile. Show username, location, etc, as well as grades . ''' User profile. Show username, location, etc, as well as grades .
We need to allow the user to change some of these settings .''' We need to allow the user to change some of these settings .'''
course_location = CourseDescriptor.id_to_location(course_id)
if student_id is None: if student_id is None:
student = request.user student = request.user
else: else:
...@@ -99,8 +118,8 @@ def profile(request, course_id, student_id=None): ...@@ -99,8 +118,8 @@ def profile(request, course_id, student_id=None):
user_info = UserProfile.objects.get(user=student) user_info = UserProfile.objects.get(user=student)
student_module_cache = StudentModuleCache(request.user, modulestore().get_item(course_location)) student_module_cache = StudentModuleCache(request.user, course)
course, _, _, _ = get_module(request.user, request, course_location, student_module_cache) course, _, _, _ = get_module(request.user, request, course.location, student_module_cache)
context = {'name': user_info.name, context = {'name': user_info.name,
'username': student.username, 'username': student.username,
...@@ -142,8 +161,9 @@ def render_accordion(request, course, chapter, section): ...@@ -142,8 +161,9 @@ def render_accordion(request, course, chapter, section):
@ensure_csrf_cookie @ensure_csrf_cookie
@check_course
@cache_control(no_cache=True, no_store=True, must_revalidate=True) @cache_control(no_cache=True, no_store=True, must_revalidate=True)
def index(request, course_id=None, chapter=None, section=None, def index(request, course, chapter=None, section=None,
position=None): position=None):
''' Displays courseware accordion, and any associated content. ''' Displays courseware accordion, and any associated content.
If course, chapter, and section aren't all specified, just returns If course, chapter, and section aren't all specified, just returns
...@@ -169,9 +189,6 @@ def index(request, course_id=None, chapter=None, section=None, ...@@ -169,9 +189,6 @@ def index(request, course_id=None, chapter=None, section=None,
''' '''
return s.replace('_', ' ') if s is not None else None return s.replace('_', ' ') if s is not None else None
course_location = CourseDescriptor.id_to_location(course_id)
course = modulestore().get_item(course_location)
chapter = clean(chapter) chapter = clean(chapter)
section = clean(section) section = clean(section)
...@@ -249,13 +266,8 @@ def jump_to(request, probname=None): ...@@ -249,13 +266,8 @@ def jump_to(request, probname=None):
@ensure_csrf_cookie @ensure_csrf_cookie
def course_info(request, course_id): @check_course
def course_info(request, course):
csrf_token = csrf(request)['csrf_token'] csrf_token = csrf(request)['csrf_token']
try:
course_location = CourseDescriptor.id_to_location(course_id)
course = modulestore().get_item(course_location)
except KeyError:
raise Http404("Course not found")
return render_to_response('info.html', {'csrf': csrf_token, 'course': course}) return render_to_response('info.html', {'csrf': csrf_token, '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