Commit 8d0eb7f1 by Brian Wilson

Respond to feedback (esp. use of .format())

parent 3b29ab37
import logging
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
import logging
from courseware.courses import get_course_by_id from courseware.courses import get_course_by_id
...@@ -20,8 +21,8 @@ class Role(models.Model): ...@@ -20,8 +21,8 @@ class Role(models.Model):
def inherit_permissions(self, role): # TODO the name of this method is a little bit confusing, def inherit_permissions(self, role): # TODO the name of this method is a little bit confusing,
# since it's one-off and doesn't handle inheritance later # since it's one-off and doesn't handle inheritance later
if role.course_id and role.course_id != self.course_id: if role.course_id and role.course_id != self.course_id:
logging.warning("%s cannot inherit permissions from %s due to course_id inconsistency" % logging.warning("{0} cannot inherit permissions from {1} due to course_id inconsistency", \
(self, role)) self, role)
for per in role.permissions.all(): for per in role.permissions.all():
self.add_permission(per) self.add_permission(per)
...@@ -30,7 +31,7 @@ class Role(models.Model): ...@@ -30,7 +31,7 @@ class Role(models.Model):
def has_permission(self, permission): def has_permission(self, permission):
course = get_course_by_id(self.course_id) course = get_course_by_id(self.course_id)
if self.name == "Student" and \ if self.name == FORUM_ROLE_STUDENT and \
(permission.startswith('edit') or permission.startswith('update') or permission.startswith('create')) and \ (permission.startswith('edit') or permission.startswith('update') or permission.startswith('create')) and \
(not course.forum_posts_allowed): (not course.forum_posts_allowed):
return False return False
......
from collections import defaultdict from collections import defaultdict
import logging
import time
import urllib
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db import connection from django.db import connection
...@@ -7,15 +11,11 @@ from django.utils import simplejson ...@@ -7,15 +11,11 @@ from django.utils import simplejson
from django_comment_client.models import Role from django_comment_client.models import Role
from django_comment_client.permissions import check_permissions_by_view from django_comment_client.permissions import check_permissions_by_view
from mitxmako import middleware from mitxmako import middleware
import pystache_custom as pystache
from xmodule.modulestore import Location from xmodule.modulestore import Location
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.modulestore.search import path_to_location from xmodule.modulestore.search import path_to_location
import logging
import pystache_custom as pystache
import time
import urllib
# TODO these should be cached via django's caching rather than in-memory globals # TODO these should be cached via django's caching rather than in-memory globals
...@@ -133,8 +133,6 @@ def initialize_discussion_info(course): ...@@ -133,8 +133,6 @@ def initialize_discussion_info(course):
return return
course_id = course.id course_id = course.id
# url_course_id = course_id.replace('/', '_').replace('.', '_')
all_modules = get_full_modules()[course_id] all_modules = get_full_modules()[course_id]
discussion_id_map = {} discussion_id_map = {}
......
...@@ -8,22 +8,21 @@ Notes for running by hand: ...@@ -8,22 +8,21 @@ Notes for running by hand:
django-admin.py test --settings=lms.envs.test --pythonpath=. lms/djangoapps/instructor django-admin.py test --settings=lms.envs.test --pythonpath=. lms/djangoapps/instructor
""" """
from courseware.access import _course_staff_group_name from override_settings import override_settings
from django.contrib.auth.models import \ from django.contrib.auth.models import \
Group # Need access to internal func to put users in the right group Group # Need access to internal func to put users in the right group
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django_comment_client.models import Role, FORUM_ROLE_ADMINISTRATOR, \ from django_comment_client.models import Role, FORUM_ROLE_ADMINISTRATOR, \
FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_STUDENT
from django_comment_client.utils import has_forum_access from django_comment_client.utils import has_forum_access
from override_settings import override_settings
from xmodule.modulestore.django import modulestore from courseware.access import _course_staff_group_name
import courseware.tests.tests as ct import courseware.tests.tests as ct
from xmodule.modulestore.django import modulestore
import xmodule.modulestore.django import xmodule.modulestore.django
@override_settings(MODULESTORE=ct.TEST_DATA_XML_MODULESTORE) @override_settings(MODULESTORE=ct.TEST_DATA_XML_MODULESTORE)
class TestInstructorDashboardGradeDownloadCSV(ct.PageLoader): class TestInstructorDashboardGradeDownloadCSV(ct.PageLoader):
''' '''
...@@ -60,22 +59,20 @@ class TestInstructorDashboardGradeDownloadCSV(ct.PageLoader): ...@@ -60,22 +59,20 @@ class TestInstructorDashboardGradeDownloadCSV(ct.PageLoader):
def test_download_grades_csv(self): def test_download_grades_csv(self):
print "running test_download_grades_csv"
course = self.toy course = self.toy
url = reverse('instructor_dashboard', kwargs={'course_id': course.id}) url = reverse('instructor_dashboard', kwargs={'course_id': course.id})
msg = "url = %s\n" % url msg = "url = {0}\n".format(url)
response = self.client.post(url, {'action': 'Download CSV of all student grades for this course', response = self.client.post(url, {'action': 'Download CSV of all student grades for this course'})
}) msg += "instructor dashboard download csv grades: response = '{0}'\n".format(response)
msg += "instructor dashboard download csv grades: response = '%s'\n" % response
self.assertEqual(response['Content-Type'],'text/csv',msg) self.assertEqual(response['Content-Type'],'text/csv',msg)
cdisp = response['Content-Disposition'].replace('TT_2012','2012') # jenkins course_id is TT_2012_Fall instead of 2012_Fall? cdisp = response['Content-Disposition'].replace('TT_2012','2012') # jenkins course_id is TT_2012_Fall instead of 2012_Fall?
msg += "cdisp = '%s'\n" % cdisp msg += "cdisp = '{0}'\n".format(cdisp)
self.assertEqual(cdisp,'attachment; filename=grades_edX/toy/2012_Fall.csv',msg) self.assertEqual(cdisp,'attachment; filename=grades_edX/toy/2012_Fall.csv',msg)
body = response.content.replace('\r','') body = response.content.replace('\r','')
msg += "body = '%s'\n" % body msg += "body = '{0}'\n".format(body)
expected_body = '''"ID","Username","Full Name","edX email","External email","HW 01","HW 02","HW 03","HW 04","HW 05","HW 06","HW 07","HW 08","HW 09","HW 10","HW 11","HW 12","HW Avg","Lab 01","Lab 02","Lab 03","Lab 04","Lab 05","Lab 06","Lab 07","Lab 08","Lab 09","Lab 10","Lab 11","Lab 12","Lab Avg","Midterm","Final" expected_body = '''"ID","Username","Full Name","edX email","External email","HW 01","HW 02","HW 03","HW 04","HW 05","HW 06","HW 07","HW 08","HW 09","HW 10","HW 11","HW 12","HW Avg","Lab 01","Lab 02","Lab 03","Lab 04","Lab 05","Lab 06","Lab 07","Lab 08","Lab 09","Lab 10","Lab 11","Lab 12","Lab Avg","Midterm","Final"
"2","u2","Fred Weasley","view2@test.com","","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0.0","0.0" "2","u2","Fred Weasley","view2@test.com","","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0.0","0.0"
...@@ -88,9 +85,9 @@ FORUM_ADMIN_USER = { FORUM_ROLE_ADMINISTRATOR : 'forumadmin', FORUM_ROLE_MODERAT ...@@ -88,9 +85,9 @@ FORUM_ADMIN_USER = { FORUM_ROLE_ADMINISTRATOR : 'forumadmin', FORUM_ROLE_MODERAT
def action_name(operation, rolename): def action_name(operation, rolename):
if operation == 'List': if operation == 'List':
return '%s course forum %ss' % (operation, FORUM_ADMIN_ACTION_SUFFIX[rolename]) return '{0} course forum {1}s'.format(operation, FORUM_ADMIN_ACTION_SUFFIX[rolename])
else: else:
return '%s forum %s' % (operation, FORUM_ADMIN_ACTION_SUFFIX[rolename]) return '{0} forum {1}'.format(operation, FORUM_ADMIN_ACTION_SUFFIX[rolename])
@override_settings(MODULESTORE=ct.TEST_DATA_XML_MODULESTORE) @override_settings(MODULESTORE=ct.TEST_DATA_XML_MODULESTORE)
class TestInstructorDashboardForumAdmin(ct.PageLoader): class TestInstructorDashboardForumAdmin(ct.PageLoader):
...@@ -132,27 +129,24 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader): ...@@ -132,27 +129,24 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader):
self.community_ta_role = Role.objects.get_or_create(name=FORUM_ROLE_COMMUNITY_TA, course_id=course_id)[0] self.community_ta_role = Role.objects.get_or_create(name=FORUM_ROLE_COMMUNITY_TA, course_id=course_id)[0]
def test_add_forum_admin_users_for_unknown_user(self): def test_add_forum_admin_users_for_unknown_user(self):
print "running test_add_forum_admin_users_for_unknown_user"
course = self.toy course = self.toy
url = reverse('instructor_dashboard', kwargs={'course_id': course.id}) url = reverse('instructor_dashboard', kwargs={'course_id': course.id})
username = 'unknown' username = 'unknown'
for action in ['Add', 'Remove']: for action in ['Add', 'Remove']:
for rolename in FORUM_ROLES: for rolename in FORUM_ROLES:
response = self.client.post(url, {'action': action_name(action, rolename), FORUM_ADMIN_USER[rolename]: username}) response = self.client.post(url, {'action': action_name(action, rolename), FORUM_ADMIN_USER[rolename]: username})
self.assertTrue(response.content.find('Error: unknown username "%s"' % username)>=0) self.assertTrue(response.content.find('Error: unknown username "{0}"'.format(username))>=0)
def test_add_forum_admin_users_for_missing_roles(self): def test_add_forum_admin_users_for_missing_roles(self):
print "test_add_forum_admin_users_for_missing_roles"
course = self.toy course = self.toy
url = reverse('instructor_dashboard', kwargs={'course_id': course.id}) url = reverse('instructor_dashboard', kwargs={'course_id': course.id})
username = 'u1' username = 'u1'
for action in ['Add', 'Remove']: for action in ['Add', 'Remove']:
for rolename in FORUM_ROLES: for rolename in FORUM_ROLES:
response = self.client.post(url, {'action': action_name(action, rolename), FORUM_ADMIN_USER[rolename]: username}) response = self.client.post(url, {'action': action_name(action, rolename), FORUM_ADMIN_USER[rolename]: username})
self.assertTrue(response.content.find('Error: unknown rolename "%s"' % rolename)>=0) self.assertTrue(response.content.find('Error: unknown rolename "{0}"'.format(rolename))>=0)
def test_remove_forum_admin_users_for_missing_users(self): def test_remove_forum_admin_users_for_missing_users(self):
print "test_remove_forum_admin_users_for_missing_users"
course = self.toy course = self.toy
self.initialize_roles(course.id) self.initialize_roles(course.id)
url = reverse('instructor_dashboard', kwargs={'course_id': course.id}) url = reverse('instructor_dashboard', kwargs={'course_id': course.id})
...@@ -160,24 +154,22 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader): ...@@ -160,24 +154,22 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader):
action = 'Remove' action = 'Remove'
for rolename in FORUM_ROLES: for rolename in FORUM_ROLES:
response = self.client.post(url, {'action': action_name(action, rolename), FORUM_ADMIN_USER[rolename]: username}) response = self.client.post(url, {'action': action_name(action, rolename), FORUM_ADMIN_USER[rolename]: username})
self.assertTrue(response.content.find('Error: user "%s" does not have rolename "%s"' % (username, rolename))>=0) self.assertTrue(response.content.find('Error: user "{0}" does not have rolename "{1}"'.format(username, rolename))>=0)
def test_add_and_remove_forum_admin_users(self): def test_add_and_remove_forum_admin_users(self):
print "test_add_and_remove_forum_admin_users"
course = self.toy course = self.toy
self.initialize_roles(course.id) self.initialize_roles(course.id)
url = reverse('instructor_dashboard', kwargs={'course_id': course.id}) url = reverse('instructor_dashboard', kwargs={'course_id': course.id})
username = 'u2' username = 'u2'
for rolename in FORUM_ROLES: for rolename in FORUM_ROLES:
response = self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username}) response = self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username})
self.assertTrue(response.content.find('Added "%s" to "%s" forum role = "%s"' % (username, course.id, rolename))>=0) self.assertTrue(response.content.find('Added "{0}" to "{1}" forum role = "{2}"'.format(username, course.id, rolename))>=0)
self.assertTrue(has_forum_access(username, course.id, rolename)) self.assertTrue(has_forum_access(username, course.id, rolename))
response = self.client.post(url, {'action': action_name('Remove', rolename), FORUM_ADMIN_USER[rolename]: username}) response = self.client.post(url, {'action': action_name('Remove', rolename), FORUM_ADMIN_USER[rolename]: username})
self.assertTrue(response.content.find('Removed "%s" from "%s" forum role = "%s"' % (username, course.id, rolename))>=0) self.assertTrue(response.content.find('Removed "{0}" from "{1}" forum role = "{2}"'.format(username, course.id, rolename))>=0)
self.assertFalse(has_forum_access(username, course.id, rolename)) self.assertFalse(has_forum_access(username, course.id, rolename))
def test_add_and_readd_forum_admin_users(self): def test_add_and_readd_forum_admin_users(self):
print "test_add_and_readd_forum_admin_users"
course = self.toy course = self.toy
self.initialize_roles(course.id) self.initialize_roles(course.id)
url = reverse('instructor_dashboard', kwargs={'course_id': course.id}) url = reverse('instructor_dashboard', kwargs={'course_id': course.id})
...@@ -186,36 +178,34 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader): ...@@ -186,36 +178,34 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader):
# perform an add, and follow with a second identical add: # perform an add, and follow with a second identical add:
self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username}) self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username})
response = self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username}) response = self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username})
self.assertTrue(response.content.find('Error: user "%s" already has rolename "%s", cannot add' % (username, rolename))>=0) self.assertTrue(response.content.find('Error: user "{0}" already has rolename "{1}", cannot add'.format(username, rolename))>=0)
self.assertTrue(has_forum_access(username, course.id, rolename)) self.assertTrue(has_forum_access(username, course.id, rolename))
def test_add_nonstaff_forum_admin_users(self): def test_add_nonstaff_forum_admin_users(self):
print "test_add_and_readd_forum_admin_users"
course = self.toy course = self.toy
self.initialize_roles(course.id) self.initialize_roles(course.id)
url = reverse('instructor_dashboard', kwargs={'course_id': course.id}) url = reverse('instructor_dashboard', kwargs={'course_id': course.id})
username = 'u1' username = 'u1'
rolename = FORUM_ROLE_ADMINISTRATOR rolename = FORUM_ROLE_ADMINISTRATOR
response = self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username}) response = self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username})
self.assertTrue(response.content.find('Error: user "%s" should first be added as staff' % username)>=0) self.assertTrue(response.content.find('Error: user "{0}" should first be added as staff'.format(username))>=0)
def test_list_forum_admin_users(self): def test_list_forum_admin_users(self):
print "test_list_forum_admin_users"
course = self.toy course = self.toy
self.initialize_roles(course.id) self.initialize_roles(course.id)
url = reverse('instructor_dashboard', kwargs={'course_id': course.id}) url = reverse('instructor_dashboard', kwargs={'course_id': course.id})
username = 'u2' username = 'u2'
added_roles = ['Student'] # u2 is already added as a student to the discussion forums added_roles = [FORUM_ROLE_STUDENT] # u2 is already added as a student to the discussion forums
self.assertTrue(has_forum_access(username, course.id, 'Student')) self.assertTrue(has_forum_access(username, course.id, 'Student'))
for rolename in FORUM_ROLES: for rolename in FORUM_ROLES:
response = self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username}) response = self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username})
self.assertTrue(has_forum_access(username, course.id, rolename)) self.assertTrue(has_forum_access(username, course.id, rolename))
response = self.client.post(url, {'action': action_name('List', rolename), FORUM_ADMIN_USER[rolename]: username}) response = self.client.post(url, {'action': action_name('List', rolename), FORUM_ADMIN_USER[rolename]: username})
for header in ['Username', 'Full name', 'Roles']: for header in ['Username', 'Full name', 'Roles']:
self.assertTrue(response.content.find('<th>%s</th>' % header)>0) self.assertTrue(response.content.find('<th>{0}</th>'.format(header))>0)
self.assertTrue(response.content.find('<td>%s</td>' % username)>=0) self.assertTrue(response.content.find('<td>{0}</td>'.format(username))>=0)
# concatenate all roles for user, in sorted order: # concatenate all roles for user, in sorted order:
added_roles.append(rolename) added_roles.append(rolename)
added_roles.sort() added_roles.sort()
roles = ', '.join(added_roles) roles = ', '.join(added_roles)
self.assertTrue(response.content.find('<td>%s</td>' % roles)>=0, 'not finding roles "%s"' % roles) self.assertTrue(response.content.find('<td>{0}</td>'.format(roles))>=0, 'not finding roles "{0}"'.format(roles))
# ======== Instructor views ============================================================================= # ======== Instructor views =============================================================================
from collections import defaultdict
import csv import csv
import logging import logging
import os import os
import urllib import urllib
import track.views
from collections import defaultdict
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
from django.http import HttpResponse from django.http import HttpResponse
from mitxmako.shortcuts import render_to_response
from django_future.csrf import ensure_csrf_cookie from django_future.csrf import ensure_csrf_cookie
from django.views.decorators.cache import cache_control from django.views.decorators.cache import cache_control
from mitxmako.shortcuts import render_to_response
from courseware import grades from courseware import grades
from courseware.access import has_access, get_access_group_name from courseware.access import has_access, get_access_group_name
from courseware.courses import get_course_with_access from courseware.courses import get_course_with_access
from django_comment_client.models import Role, FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA
from django_comment_client.utils import has_forum_access
from psychometrics import psychoanalyze from psychometrics import psychoanalyze
from student.models import CourseEnrollment from student.models import CourseEnrollment
from xmodule.course_module import CourseDescriptor from xmodule.course_module import CourseDescriptor
from xmodule.modulestore import Location from xmodule.modulestore import Location
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import InvalidLocationError, ItemNotFoundError, NoPathToItem from xmodule.modulestore.exceptions import InvalidLocationError, ItemNotFoundError, NoPathToItem
from xmodule.modulestore.search import path_to_location from xmodule.modulestore.search import path_to_location
from django_comment_client.models import Role, FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA import track.views
from django_comment_client.utils import has_forum_access
log = logging.getLogger("mitx.courseware") log = logging.getLogger("mitx.courseware")
...@@ -50,8 +47,6 @@ def instructor_dashboard(request, course_id): ...@@ -50,8 +47,6 @@ def instructor_dashboard(request, course_id):
forum_admin_access = has_forum_access(request.user, course_id, FORUM_ROLE_ADMINISTRATOR) forum_admin_access = has_forum_access(request.user, course_id, FORUM_ROLE_ADMINISTRATOR)
msg = '' msg = ''
#msg += ('POST=%s' % dict(request.POST)).replace('<','&lt;')
problems = [] problems = []
plots = [] plots = []
...@@ -79,7 +74,7 @@ def instructor_dashboard(request, course_id): ...@@ -79,7 +74,7 @@ def instructor_dashboard(request, course_id):
def return_csv(fn, datatable): def return_csv(fn, datatable):
response = HttpResponse(mimetype='text/csv') response = HttpResponse(mimetype='text/csv')
response['Content-Disposition'] = 'attachment; filename=%s' % fn response['Content-Disposition'] = 'attachment; filename={0}'.format(fn)
writer = csv.writer(response, dialect='excel', quotechar='"', quoting=csv.QUOTE_ALL) writer = csv.writer(response, dialect='excel', quotechar='"', quoting=csv.QUOTE_ALL)
writer.writerow(datatable['header']) writer.writerow(datatable['header'])
for datarow in datatable['data']: for datarow in datatable['data']:
...@@ -102,75 +97,75 @@ def instructor_dashboard(request, course_id): ...@@ -102,75 +97,75 @@ def instructor_dashboard(request, course_id):
if settings.MITX_FEATURES['ENABLE_MANUAL_GIT_RELOAD']: if settings.MITX_FEATURES['ENABLE_MANUAL_GIT_RELOAD']:
if 'GIT pull' in action: if 'GIT pull' in action:
data_dir = course.metadata['data_dir'] data_dir = course.metadata['data_dir']
log.debug('git pull %s' % (data_dir)) log.debug('git pull {0}'.format(data_dir))
gdir = settings.DATA_DIR / data_dir gdir = settings.DATA_DIR / data_dir
if not os.path.exists(gdir): if not os.path.exists(gdir):
msg += "====> ERROR in gitreload - no such directory %s" % gdir msg += "====> ERROR in gitreload - no such directory {0}".format(gdir)
else: else:
cmd = "cd %s; git reset --hard HEAD; git clean -f -d; git pull origin; chmod g+w course.xml" % gdir cmd = "cd {0}; git reset --hard HEAD; git clean -f -d; git pull origin; chmod g+w course.xml".format(gdir)
msg += "git pull on %s:<p>" % data_dir msg += "git pull on {0}:<p>".format(data_dir)
msg += "<pre>%s</pre></p>" % escape(os.popen(cmd).read()) msg += "<pre>{0}</pre></p>".format(escape(os.popen(cmd).read()))
track.views.server_track(request, 'git pull %s' % data_dir, {}, page='idashboard') track.views.server_track(request, 'git pull {0}'.format(data_dir), {}, page='idashboard')
if 'Reload course' in action: if 'Reload course' in action:
log.debug('reloading %s (%s)' % (course_id, course)) log.debug('reloading {0} ({1})'.format(course_id, course))
try: try:
data_dir = course.metadata['data_dir'] data_dir = course.metadata['data_dir']
modulestore().try_load_course(data_dir) modulestore().try_load_course(data_dir)
msg += "<br/><p>Course reloaded from %s</p>" % data_dir msg += "<br/><p>Course reloaded from {0}</p>".format(data_dir)
track.views.server_track(request, 'reload %s' % data_dir, {}, page='idashboard') track.views.server_track(request, 'reload {0}'.format(data_dir), {}, page='idashboard')
course_errors = modulestore().get_item_errors(course.location) course_errors = modulestore().get_item_errors(course.location)
msg += '<ul>' msg += '<ul>'
for cmsg, cerr in course_errors: for cmsg, cerr in course_errors:
msg += "<li>%s: <pre>%s</pre>" % (cmsg,escape(cerr)) msg += "<li>{0}: <pre>{1}</pre>".format(cmsg,escape(cerr))
msg += '</ul>' msg += '</ul>'
except Exception as err: except Exception as err:
msg += '<br/><p>Error: %s</p>' % escape(err) msg += '<br/><p>Error: {0}</p>'.format(escape(err))
if action == 'Dump list of enrolled students': if action == 'Dump list of enrolled students':
log.debug(action) log.debug(action)
datatable = get_student_grade_summary_data(request, course, course_id, get_grades=False) datatable = get_student_grade_summary_data(request, course, course_id, get_grades=False)
datatable['title'] = 'List of students enrolled in %s' % course_id datatable['title'] = 'List of students enrolled in {0}'.format(course_id)
track.views.server_track(request, 'list-students', {}, page='idashboard') track.views.server_track(request, 'list-students', {}, page='idashboard')
elif 'Dump Grades' in action: elif 'Dump Grades' in action:
log.debug(action) log.debug(action)
datatable = get_student_grade_summary_data(request, course, course_id, get_grades=True) datatable = get_student_grade_summary_data(request, course, course_id, get_grades=True)
datatable['title'] = 'Summary Grades of students enrolled in %s' % course_id datatable['title'] = 'Summary Grades of students enrolled in {0}'.format(course_id)
track.views.server_track(request, 'dump-grades', {}, page='idashboard') track.views.server_track(request, 'dump-grades', {}, page='idashboard')
elif 'Dump all RAW grades' in action: elif 'Dump all RAW grades' in action:
log.debug(action) log.debug(action)
datatable = get_student_grade_summary_data(request, course, course_id, get_grades=True, datatable = get_student_grade_summary_data(request, course, course_id, get_grades=True,
get_raw_scores=True) get_raw_scores=True)
datatable['title'] = 'Raw Grades of students enrolled in %s' % course_id datatable['title'] = 'Raw Grades of students enrolled in {0}'.format(course_id)
track.views.server_track(request, 'dump-grades-raw', {}, page='idashboard') track.views.server_track(request, 'dump-grades-raw', {}, page='idashboard')
elif 'Download CSV of all student grades' in action: elif 'Download CSV of all student grades' in action:
track.views.server_track(request, 'dump-grades-csv', {}, page='idashboard') track.views.server_track(request, 'dump-grades-csv', {}, page='idashboard')
return return_csv('grades_%s.csv' % course_id, return return_csv('grades_{0}.csv'.format(course_id),
get_student_grade_summary_data(request, course, course_id)) get_student_grade_summary_data(request, course, course_id))
elif 'Download CSV of all RAW grades' in action: elif 'Download CSV of all RAW grades' in action:
track.views.server_track(request, 'dump-grades-csv-raw', {}, page='idashboard') track.views.server_track(request, 'dump-grades-csv-raw', {}, page='idashboard')
return return_csv('grades_%s_raw.csv' % course_id, return return_csv('grades_{0}_raw.csv'.format(course_id),
get_student_grade_summary_data(request, course, course_id, get_raw_scores=True)) get_student_grade_summary_data(request, course, course_id, get_raw_scores=True))
elif 'Download CSV of answer distributions' in action: elif 'Download CSV of answer distributions' in action:
track.views.server_track(request, 'dump-answer-dist-csv', {}, page='idashboard') track.views.server_track(request, 'dump-answer-dist-csv', {}, page='idashboard')
return return_csv('answer_dist_%s.csv' % course_id, get_answers_distribution(request, course_id)) return return_csv('answer_dist_{0}.csv'.format(course_id), get_answers_distribution(request, course_id))
#---------------------------------------- #----------------------------------------
# Admin # Admin
elif 'List course staff' in action: elif 'List course staff' in action:
group = get_staff_group(course) group = get_staff_group(course)
msg += 'Staff group = %s' % group.name msg += 'Staff group = {0}'.format(group.name)
log.debug('staffgrp=%s' % group.name) log.debug('staffgrp={0}'.format(group.name))
uset = group.user_set.all() uset = group.user_set.all()
datatable = {'header': ['Username', 'Full name']} datatable = {'header': ['Username', 'Full name']}
datatable['data'] = [[x.username, x.profile.name] for x in uset] datatable['data'] = [[x.username, x.profile.name] for x in uset]
datatable['title'] = 'List of Staff in course %s' % course_id datatable['title'] = 'List of Staff in course {0}'.format(course_id)
track.views.server_track(request, 'list-staff', {}, page='idashboard') track.views.server_track(request, 'list-staff', {}, page='idashboard')
elif action == 'Add course staff': elif action == 'Add course staff':
...@@ -178,28 +173,28 @@ def instructor_dashboard(request, course_id): ...@@ -178,28 +173,28 @@ def instructor_dashboard(request, course_id):
try: try:
user = User.objects.get(username=uname) user = User.objects.get(username=uname)
except User.DoesNotExist: except User.DoesNotExist:
msg += '<font color="red">Error: unknown username "%s"</font>' % uname msg += '<font color="red">Error: unknown username "{0}"</font>'.format(uname)
user = None user = None
if user is not None: if user is not None:
group = get_staff_group(course) group = get_staff_group(course)
msg += '<font color="green">Added %s to staff group = %s</font>' % (user, group.name) msg += '<font color="green">Added {0} to staff group = {1}</font>'.format(user, group.name)
log.debug('staffgrp=%s' % group.name) log.debug('staffgrp={0}'.format(group.name))
user.groups.add(group) user.groups.add(group)
track.views.server_track(request, 'add-staff %s' % user, {}, page='idashboard') track.views.server_track(request, 'add-staff {0}'.format(user), {}, page='idashboard')
elif action == 'Remove course staff': elif action == 'Remove course staff':
uname = request.POST['staffuser'] uname = request.POST['staffuser']
try: try:
user = User.objects.get(username=uname) user = User.objects.get(username=uname)
except User.DoesNotExist: except User.DoesNotExist:
msg += '<font color="red">Error: unknown username "%s"</font>' % uname msg += '<font color="red">Error: unknown username "{0}"</font>'.format(uname)
user = None user = None
if user is not None: if user is not None:
group = get_staff_group(course) group = get_staff_group(course)
msg += '<font color="green">Removed %s from staff group = %s</font>' % (user, group.name) msg += '<font color="green">Removed {0} from staff group = {1}</font>'.format(user, group.name)
log.debug('staffgrp=%s' % group.name) log.debug('staffgrp={0}'.format(group.name))
user.groups.remove(group) user.groups.remove(group)
track.views.server_track(request, 'remove-staff %s' % user, {}, page='idashboard') track.views.server_track(request, 'remove-staff {0}'.format(user), {}, page='idashboard')
#---------------------------------------- #----------------------------------------
# forum administration # forum administration
...@@ -208,55 +203,55 @@ def instructor_dashboard(request, course_id): ...@@ -208,55 +203,55 @@ def instructor_dashboard(request, course_id):
rolename = FORUM_ROLE_ADMINISTRATOR rolename = FORUM_ROLE_ADMINISTRATOR
datatable = {} datatable = {}
msg += _list_course_forum_members(course_id, rolename, datatable) msg += _list_course_forum_members(course_id, rolename, datatable)
track.views.server_track(request, 'list-%s' % rolename, {}, page='idashboard') track.views.server_track(request, 'list-{0}'.format(rolename), {}, page='idashboard')
elif action == 'Remove forum admin': elif action == 'Remove forum admin':
uname = request.POST['forumadmin'] uname = request.POST['forumadmin']
msg += _update_forum_role_membership(uname, course, FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_REMOVE) msg += _update_forum_role_membership(uname, course, FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_REMOVE)
track.views.server_track(request, '%s %s as %s for %s' % (FORUM_ROLE_REMOVE, uname, FORUM_ROLE_ADMINISTRATOR, course_id), track.views.server_track(request, '{0} {1} as {2} for {3}'.format(FORUM_ROLE_REMOVE, uname, FORUM_ROLE_ADMINISTRATOR, course_id),
{}, page='idashboard') {}, page='idashboard')
elif action == 'Add forum admin': elif action == 'Add forum admin':
uname = request.POST['forumadmin'] uname = request.POST['forumadmin']
msg += _update_forum_role_membership(uname, course, FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_ADD) msg += _update_forum_role_membership(uname, course, FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_ADD)
track.views.server_track(request, '%s %s as %s for %s' % (FORUM_ROLE_ADD, uname, FORUM_ROLE_ADMINISTRATOR, course_id), track.views.server_track(request, '{0} {1} as {2} for {3}'.format(FORUM_ROLE_ADD, uname, FORUM_ROLE_ADMINISTRATOR, course_id),
{}, page='idashboard') {}, page='idashboard')
elif action == 'List course forum moderators': elif action == 'List course forum moderators':
rolename = FORUM_ROLE_MODERATOR rolename = FORUM_ROLE_MODERATOR
datatable = {} datatable = {}
msg += _list_course_forum_members(course_id, rolename, datatable) msg += _list_course_forum_members(course_id, rolename, datatable)
track.views.server_track(request, 'list-%s' % rolename, {}, page='idashboard') track.views.server_track(request, 'list-{0}'.format(rolename), {}, page='idashboard')
elif action == 'Remove forum moderator': elif action == 'Remove forum moderator':
uname = request.POST['forummoderator'] uname = request.POST['forummoderator']
msg += _update_forum_role_membership(uname, course, FORUM_ROLE_MODERATOR, FORUM_ROLE_REMOVE) msg += _update_forum_role_membership(uname, course, FORUM_ROLE_MODERATOR, FORUM_ROLE_REMOVE)
track.views.server_track(request, '%s %s as %s for %s' % (FORUM_ROLE_REMOVE, uname, FORUM_ROLE_MODERATOR, course_id), track.views.server_track(request, '{0} {1} as {2} for {3}'.format(FORUM_ROLE_REMOVE, uname, FORUM_ROLE_MODERATOR, course_id),
{}, page='idashboard') {}, page='idashboard')
elif action == 'Add forum moderator': elif action == 'Add forum moderator':
uname = request.POST['forummoderator'] uname = request.POST['forummoderator']
msg += _update_forum_role_membership(uname, course, FORUM_ROLE_MODERATOR, FORUM_ROLE_ADD) msg += _update_forum_role_membership(uname, course, FORUM_ROLE_MODERATOR, FORUM_ROLE_ADD)
track.views.server_track(request, '%s %s as %s for %s' % (FORUM_ROLE_ADD, uname, FORUM_ROLE_MODERATOR, course_id), track.views.server_track(request, '{0} {1} as {2} for {3}'.format(FORUM_ROLE_ADD, uname, FORUM_ROLE_MODERATOR, course_id),
{}, page='idashboard') {}, page='idashboard')
elif action == 'List course forum community TAs': elif action == 'List course forum community TAs':
rolename = FORUM_ROLE_COMMUNITY_TA rolename = FORUM_ROLE_COMMUNITY_TA
datatable = {} datatable = {}
msg += _list_course_forum_members(course_id, rolename, datatable) msg += _list_course_forum_members(course_id, rolename, datatable)
track.views.server_track(request, 'list-%s' % rolename, {}, page='idashboard') track.views.server_track(request, 'list-{0}'.format(rolename), {}, page='idashboard')
elif action == 'Remove forum community TA': elif action == 'Remove forum community TA':
uname = request.POST['forummoderator'] uname = request.POST['forummoderator']
msg += _update_forum_role_membership(uname, course, FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_REMOVE) msg += _update_forum_role_membership(uname, course, FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_REMOVE)
track.views.server_track(request, '%s %s as %s for %s' % (FORUM_ROLE_REMOVE, uname, FORUM_ROLE_COMMUNITY_TA, course_id), track.views.server_track(request, '{0} {1} as {2} for {3}'.format(FORUM_ROLE_REMOVE, uname, FORUM_ROLE_COMMUNITY_TA, course_id),
{}, page='idashboard') {}, page='idashboard')
elif action == 'Add forum community TA': elif action == 'Add forum community TA':
uname = request.POST['forummoderator'] uname = request.POST['forummoderator']
msg += _update_forum_role_membership(uname, course, FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_ADD) msg += _update_forum_role_membership(uname, course, FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_ADD)
track.views.server_track(request, '%s %s as %s for %s' % (FORUM_ROLE_ADD, uname, FORUM_ROLE_COMMUNITY_TA, course_id), track.views.server_track(request, '{0} {1} as {2} for {3}'.format(FORUM_ROLE_ADD, uname, FORUM_ROLE_COMMUNITY_TA, course_id),
{}, page='idashboard') {}, page='idashboard')
#---------------------------------------- #----------------------------------------
...@@ -266,7 +261,7 @@ def instructor_dashboard(request, course_id): ...@@ -266,7 +261,7 @@ def instructor_dashboard(request, course_id):
problem = request.POST['Problem'] problem = request.POST['Problem']
nmsg, plots = psychoanalyze.generate_plots_for_problem(problem) nmsg, plots = psychoanalyze.generate_plots_for_problem(problem)
msg += nmsg msg += nmsg
track.views.server_track(request, 'psychometrics %s' % problem, {}, page='idashboard') track.views.server_track(request, 'psychometrics {0}'.format(problem), {}, page='idashboard')
if idash_mode=='Psychometrics': if idash_mode=='Psychometrics':
problems = psychoanalyze.problems_with_psychometric_data(course_id) problems = psychoanalyze.problems_with_psychometric_data(course_id)
...@@ -303,15 +298,15 @@ def _list_course_forum_members(course_id, rolename, datatable): ...@@ -303,15 +298,15 @@ def _list_course_forum_members(course_id, rolename, datatable):
''' '''
# make sure datatable is set up properly for display first, before checking for errors # make sure datatable is set up properly for display first, before checking for errors
datatable['header'] = ['Username', 'Full name', 'Roles'] datatable['header'] = ['Username', 'Full name', 'Roles']
datatable['title'] = 'List of Forum %ss in course %s' % (rolename, course_id) datatable['title'] = 'List of Forum {0}s in course {1}'.format(rolename, course_id)
datatable['data'] = []; datatable['data'] = [];
try: try:
role = Role.objects.get(name=rolename, course_id=course_id) role = Role.objects.get(name=rolename, course_id=course_id)
except Role.DoesNotExist: except Role.DoesNotExist:
return '<font color="red">Error: unknown rolename "%s"</font>' % rolename return '<font color="red">Error: unknown rolename "{0}"</font>'.format(rolename)
uset = role.users.all().order_by('username') uset = role.users.all().order_by('username')
msg = 'Role = %s' % rolename msg = 'Role = {0}'.format(rolename)
log.debug('role=%s' % rolename) log.debug('role={0}'.format(rolename))
datatable['data'] = [[x.username, x.profile.name, ', '.join([r.name for r in x.roles.filter(course_id=course_id).order_by('name')])] for x in uset] datatable['data'] = [[x.username, x.profile.name, ', '.join([r.name for r in x.roles.filter(course_id=course_id).order_by('name')])] for x in uset]
return msg return msg
...@@ -332,31 +327,31 @@ def _update_forum_role_membership(uname, course, rolename, add_or_remove): ...@@ -332,31 +327,31 @@ def _update_forum_role_membership(uname, course, rolename, add_or_remove):
try: try:
user = User.objects.get(username=uname) user = User.objects.get(username=uname)
except User.DoesNotExist: except User.DoesNotExist:
return '<font color="red">Error: unknown username "%s"</font>' % uname return '<font color="red">Error: unknown username "{0}"</font>'.format(uname)
try: try:
role = Role.objects.get(name=rolename, course_id=course.id) role = Role.objects.get(name=rolename, course_id=course.id)
except Role.DoesNotExist: except Role.DoesNotExist:
return '<font color="red">Error: unknown rolename "%s"</font>' % rolename return '<font color="red">Error: unknown rolename "{0}"</font>'.format(rolename)
# check whether role already has the specified user: # check whether role already has the specified user:
alreadyexists = role.users.filter(username=uname).exists() alreadyexists = role.users.filter(username=uname).exists()
msg = '' msg = ''
log.debug('rolename=%s' % rolename) log.debug('rolename={0}'.format(rolename))
if (add_or_remove == FORUM_ROLE_REMOVE): if add_or_remove == FORUM_ROLE_REMOVE:
if (not alreadyexists): if not alreadyexists:
msg ='<font color="red">Error: user "%s" does not have rolename "%s", cannot remove</font>' % (uname, rolename) msg ='<font color="red">Error: user "{0}" does not have rolename "{1}", cannot remove</font>'.format(uname, rolename)
else: else:
user.roles.remove(role) user.roles.remove(role)
msg = '<font color="green">Removed "%s" from "%s" forum role = "%s"</font>' % (user, course.id, rolename) msg = '<font color="green">Removed "{0}" from "{1}" forum role = "{2}"</font>'.format(user, course.id, rolename)
else: else:
if (alreadyexists): if alreadyexists:
msg = '<font color="red">Error: user "%s" already has rolename "%s", cannot add</font>' % (uname, rolename) msg = '<font color="red">Error: user "{0}" already has rolename "{1}", cannot add</font>'.format(uname, rolename)
else: else:
if (rolename == FORUM_ROLE_ADMINISTRATOR and not has_access(user, course, 'staff')): if (rolename == FORUM_ROLE_ADMINISTRATOR and not has_access(user, course, 'staff')):
msg = '<font color="red">Error: user "%s" should first be added as staff before adding as a forum administrator, cannot add</font>' % uname msg = '<font color="red">Error: user "{0}" should first be added as staff before adding as a forum administrator, cannot add</font>'.format(uname)
else: else:
user.roles.add(role) user.roles.add(role)
msg = '<font color="green">Added "%s" to "%s" forum role = "%s"</font>' % (user, course.id, rolename) msg = '<font color="green">Added "{0}" to "{1}" forum role = "{2}"</font>'.format(user, course.id, rolename)
return msg return msg
...@@ -385,7 +380,7 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True, ...@@ -385,7 +380,7 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True,
if get_grades: if get_grades:
# just to construct the header # just to construct the header
gradeset = grades.grade(enrolled_students[0], request, course, keep_raw_scores=get_raw_scores) gradeset = grades.grade(enrolled_students[0], request, course, keep_raw_scores=get_raw_scores)
# log.debug('student %s gradeset %s' % (enrolled_students[0], gradeset)) # log.debug('student {0} gradeset {1}'.format(enrolled_students[0], gradeset))
if get_raw_scores: if get_raw_scores:
header += [score.section for score in gradeset['raw_scores']] header += [score.section for score in gradeset['raw_scores']]
else: else:
...@@ -403,7 +398,7 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True, ...@@ -403,7 +398,7 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True,
if get_grades: if get_grades:
gradeset = grades.grade(student, request, course, keep_raw_scores=get_raw_scores) gradeset = grades.grade(student, request, course, keep_raw_scores=get_raw_scores)
# log.debug('student=%s, gradeset=%s' % (student,gradeset)) # log.debug('student={0}, gradeset={1}'.format(student,gradeset))
if get_raw_scores: if get_raw_scores:
datarow += [score.earned for score in gradeset['raw_scores']] datarow += [score.earned for score in gradeset['raw_scores']]
else: else:
......
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