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
import logging
from path import path
......@@ -13,6 +15,14 @@ log = logging.getLogger(__name__)
class CourseDescriptor(SequenceDescriptor):
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
def id_to_location(cls, course_id):
org, course, name = course_id.split('/')
......@@ -24,7 +34,7 @@ class CourseDescriptor(SequenceDescriptor):
@property
def title(self):
self.metadata['display_name']
return self.metadata['display_name']
@property
def instructors(self):
......@@ -69,6 +79,7 @@ class CourseDescriptor(SequenceDescriptor):
elif section_key == "title":
return self.metadata.get('display_name', self.name)
elif section_key == "university":
return self.metadata.get('start')
return self.location.org
elif section_key == "number":
return self.number
......
......@@ -214,7 +214,7 @@ class XModuleDescriptor(Plugin):
# A list of metadata that this module can inherit from its parent module
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,
# and will need to be removed when that code is removed
......@@ -251,6 +251,7 @@ class XModuleDescriptor(Plugin):
display_name: The name to use for displaying this module to the user
format: The format of this module ('Homework', 'Lab', etc)
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
graceperiod (string): The amount of grace period to allow when enforcing the due date
showanswer (string): When to show answers for this module
......
......@@ -88,7 +88,7 @@ class XmlDescriptor(XModuleDescriptor):
# The attributes will be removed from the definition xml passed
# to definition_from_xml, and from the xml returned by definition_to_xml
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
# that return the metadata key and value
......
......@@ -27,6 +27,25 @@ log = logging.getLogger("mitx.courseware")
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):
if not user.is_authenticated():
......@@ -84,12 +103,12 @@ def gradebook(request, course_id):
@login_required
@check_course
@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 .
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:
student = request.user
else:
......@@ -99,8 +118,8 @@ def profile(request, course_id, student_id=None):
user_info = UserProfile.objects.get(user=student)
student_module_cache = StudentModuleCache(request.user, modulestore().get_item(course_location))
course, _, _, _ = get_module(request.user, request, course_location, student_module_cache)
student_module_cache = StudentModuleCache(request.user, course)
course, _, _, _ = get_module(request.user, request, course.location, student_module_cache)
context = {'name': user_info.name,
'username': student.username,
......@@ -142,8 +161,9 @@ def render_accordion(request, course, chapter, section):
@ensure_csrf_cookie
@check_course
@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):
''' Displays courseware accordion, and any associated content.
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,
'''
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)
section = clean(section)
......@@ -249,13 +266,8 @@ def jump_to(request, probname=None):
@ensure_csrf_cookie
def course_info(request, course_id):
@check_course
def course_info(request, course):
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})
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