Merge pull request #676 from edx/diana/course-modes
Add Course Modes to LMS
This commit is contained in:
0
lms/djangoapps/course_modes/__init__.py
Normal file
0
lms/djangoapps/course_modes/__init__.py
Normal file
4
lms/djangoapps/course_modes/admin.py
Normal file
4
lms/djangoapps/course_modes/admin.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from ratelimitbackend import admin
|
||||
from course_modes.models import CourseMode
|
||||
|
||||
admin.site.register(CourseMode)
|
||||
40
lms/djangoapps/course_modes/migrations/0001_initial.py
Normal file
40
lms/djangoapps/course_modes/migrations/0001_initial.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding model 'CourseMode'
|
||||
db.create_table('course_modes_coursemode', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('course_id', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True)),
|
||||
('mode_slug', self.gf('django.db.models.fields.CharField')(max_length=100)),
|
||||
('mode_display_name', self.gf('django.db.models.fields.CharField')(max_length=255)),
|
||||
('min_price', self.gf('django.db.models.fields.IntegerField')(default=0)),
|
||||
('suggested_prices', self.gf('django.db.models.fields.CommaSeparatedIntegerField')(default='', max_length=255, blank=True)),
|
||||
))
|
||||
db.send_create_signal('course_modes', ['CourseMode'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting model 'CourseMode'
|
||||
db.delete_table('course_modes_coursemode')
|
||||
|
||||
|
||||
models = {
|
||||
'course_modes.coursemode': {
|
||||
'Meta': {'object_name': 'CourseMode'},
|
||||
'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'min_price': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'mode_display_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'mode_slug': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'suggested_prices': ('django.db.models.fields.CommaSeparatedIntegerField', [], {'default': "''", 'max_length': '255', 'blank': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['course_modes']
|
||||
0
lms/djangoapps/course_modes/migrations/__init__.py
Normal file
0
lms/djangoapps/course_modes/migrations/__init__.py
Normal file
46
lms/djangoapps/course_modes/models.py
Normal file
46
lms/djangoapps/course_modes/models.py
Normal file
@@ -0,0 +1,46 @@
|
||||
"""
|
||||
Add and create new modes for running courses on this particular LMS
|
||||
"""
|
||||
from django.db import models
|
||||
from collections import namedtuple
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
Mode = namedtuple('Mode', ['slug', 'name', 'min_price', 'suggested_prices'])
|
||||
|
||||
|
||||
class CourseMode(models.Model):
|
||||
"""
|
||||
We would like to offer a course in a variety of modes.
|
||||
|
||||
"""
|
||||
# the course that this mode is attached to
|
||||
course_id = models.CharField(max_length=255, db_index=True)
|
||||
|
||||
# the reference to this mode that can be used by Enrollments to generate
|
||||
# similar behavior for the same slug across courses
|
||||
mode_slug = models.CharField(max_length=100)
|
||||
|
||||
# The 'pretty' name that can be translated and displayed
|
||||
mode_display_name = models.CharField(max_length=255)
|
||||
|
||||
# minimum price in USD that we would like to charge for this mode of the course
|
||||
min_price = models.IntegerField(default=0)
|
||||
|
||||
# the suggested prices for this mode
|
||||
suggested_prices = models.CommaSeparatedIntegerField(max_length=255, blank=True, default='')
|
||||
|
||||
DEFAULT_MODE = Mode('honor', _('Honor Code Certificate'), 0, '')
|
||||
|
||||
@classmethod
|
||||
def modes_for_course(cls, course_id):
|
||||
"""
|
||||
Returns a list of the modes for a given course id
|
||||
|
||||
If no modes have been set in the table, returns the default mode
|
||||
"""
|
||||
found_course_modes = cls.objects.filter(course_id=course_id)
|
||||
modes = ([Mode(mode.mode_slug, mode.mode_display_name, mode.min_price, mode.suggested_prices)
|
||||
for mode in found_course_modes])
|
||||
if not modes:
|
||||
modes = [cls.DEFAULT_MODE]
|
||||
return modes
|
||||
61
lms/djangoapps/course_modes/tests.py
Normal file
61
lms/djangoapps/course_modes/tests.py
Normal file
@@ -0,0 +1,61 @@
|
||||
"""
|
||||
This file demonstrates writing tests using the unittest module. These will pass
|
||||
when you run "manage.py test".
|
||||
|
||||
Replace this with more appropriate tests for your application.
|
||||
"""
|
||||
|
||||
from django.test import TestCase
|
||||
from course_modes.models import CourseMode, Mode
|
||||
|
||||
|
||||
class CourseModeModelTest(TestCase):
|
||||
"""
|
||||
Tests for the CourseMode model
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.course_id = 'TestCourse'
|
||||
CourseMode.objects.all().delete()
|
||||
|
||||
def create_mode(self, mode_slug, mode_name, min_price=0, suggested_prices=''):
|
||||
"""
|
||||
Create a new course mode
|
||||
"""
|
||||
CourseMode.objects.get_or_create(
|
||||
course_id=self.course_id,
|
||||
mode_display_name=mode_name,
|
||||
mode_slug=mode_slug,
|
||||
min_price=min_price,
|
||||
suggested_prices=suggested_prices
|
||||
)
|
||||
|
||||
def test_modes_for_course_empty(self):
|
||||
"""
|
||||
If we can't find any modes, we should get back the default mode
|
||||
"""
|
||||
# shouldn't be able to find a corresponding course
|
||||
modes = CourseMode.modes_for_course(self.course_id)
|
||||
self.assertEqual([CourseMode.DEFAULT_MODE], modes)
|
||||
|
||||
def test_nodes_for_course_single(self):
|
||||
"""
|
||||
Find the modes for a course with only one mode
|
||||
"""
|
||||
|
||||
self.create_mode('verified', 'Verified Certificate')
|
||||
modes = CourseMode.modes_for_course(self.course_id)
|
||||
self.assertEqual([Mode(u'verified', u'Verified Certificate', 0, '')], modes)
|
||||
|
||||
def test_modes_for_course_multiple(self):
|
||||
"""
|
||||
Finding the modes when there's multiple modes
|
||||
"""
|
||||
mode1 = Mode(u'honor', u'Honor Code Certificate', 0, '')
|
||||
mode2 = Mode(u'verified', u'Verified Certificate', 0, '')
|
||||
set_modes = [mode1, mode2]
|
||||
for mode in set_modes:
|
||||
self.create_mode(mode.slug, mode.name, mode.min_price, mode.suggested_prices)
|
||||
|
||||
modes = CourseMode.modes_for_course(self.course_id)
|
||||
self.assertEqual(modes, set_modes)
|
||||
1
lms/djangoapps/course_modes/views.py
Normal file
1
lms/djangoapps/course_modes/views.py
Normal file
@@ -0,0 +1 @@
|
||||
# Create your views here.
|
||||
@@ -771,6 +771,9 @@ INSTALLED_APPS = (
|
||||
|
||||
# Notification preferences setting
|
||||
'notification_prefs',
|
||||
|
||||
# Different Course Modes
|
||||
'course_modes'
|
||||
)
|
||||
|
||||
######################### MARKETING SITE ###############################
|
||||
|
||||
Reference in New Issue
Block a user