Commit 3df02d9c by ichuang

pep8 fixes

parent b7415b7d
...@@ -61,6 +61,7 @@ from xmodule.modulestore.django import modulestore ...@@ -61,6 +61,7 @@ from xmodule.modulestore.django import modulestore
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class UserProfile(models.Model): class UserProfile(models.Model):
"""This is where we store all the user demographic fields. We have a """This is where we store all the user demographic fields. We have a
separate table for this rather than extending the built-in Django auth_user. separate table for this rather than extending the built-in Django auth_user.
...@@ -175,6 +176,7 @@ class PendingEmailChange(models.Model): ...@@ -175,6 +176,7 @@ class PendingEmailChange(models.Model):
new_email = models.CharField(blank=True, max_length=255, db_index=True) new_email = models.CharField(blank=True, max_length=255, db_index=True)
activation_key = models.CharField(('activation key'), max_length=32, unique=True, db_index=True) activation_key = models.CharField(('activation key'), max_length=32, unique=True, db_index=True)
class CourseEnrollment(models.Model): class CourseEnrollment(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
course_id = models.CharField(max_length=255, db_index=True) course_id = models.CharField(max_length=255, db_index=True)
...@@ -185,7 +187,8 @@ class CourseEnrollment(models.Model): ...@@ -185,7 +187,8 @@ class CourseEnrollment(models.Model):
unique_together = (('user', 'course_id'), ) unique_together = (('user', 'course_id'), )
def __unicode__(self): def __unicode__(self):
return "%s: %s (%s)" % (self.user,self.course_id,self.created) return "%s: %s (%s)" % (self.user, self.course_id, self.created)
@receiver(post_save, sender=CourseEnrollment) @receiver(post_save, sender=CourseEnrollment)
def assign_default_role(sender, instance, **kwargs): def assign_default_role(sender, instance, **kwargs):
...@@ -276,6 +279,7 @@ def add_user_to_default_group(user, group): ...@@ -276,6 +279,7 @@ def add_user_to_default_group(user, group):
utg.users.add(User.objects.get(username=user)) utg.users.add(User.objects.get(username=user))
utg.save() utg.save()
@receiver(post_save, sender=User) @receiver(post_save, sender=User)
def update_user_information(sender, instance, created, **kwargs): def update_user_information(sender, instance, created, **kwargs):
try: try:
...@@ -286,6 +290,7 @@ def update_user_information(sender, instance, created, **kwargs): ...@@ -286,6 +290,7 @@ def update_user_information(sender, instance, created, **kwargs):
log.error(unicode(e)) log.error(unicode(e))
log.error("update user info to discussion failed for user with id: " + str(instance.id)) log.error("update user info to discussion failed for user with id: " + str(instance.id))
########################## REPLICATION SIGNALS ################################# ########################## REPLICATION SIGNALS #################################
# @receiver(post_save, sender=User) # @receiver(post_save, sender=User)
def replicate_user_save(sender, **kwargs): def replicate_user_save(sender, **kwargs):
...@@ -295,6 +300,7 @@ def replicate_user_save(sender, **kwargs): ...@@ -295,6 +300,7 @@ def replicate_user_save(sender, **kwargs):
for course_db_name in db_names_to_replicate_to(user_obj.id): for course_db_name in db_names_to_replicate_to(user_obj.id):
replicate_user(user_obj, course_db_name) replicate_user(user_obj, course_db_name)
# @receiver(post_save, sender=CourseEnrollment) # @receiver(post_save, sender=CourseEnrollment)
def replicate_enrollment_save(sender, **kwargs): def replicate_enrollment_save(sender, **kwargs):
"""This is called when a Student enrolls in a course. It has to do the """This is called when a Student enrolls in a course. It has to do the
...@@ -321,11 +327,13 @@ def replicate_enrollment_save(sender, **kwargs): ...@@ -321,11 +327,13 @@ def replicate_enrollment_save(sender, **kwargs):
user_profile = UserProfile.objects.get(user_id=enrollment_obj.user_id) user_profile = UserProfile.objects.get(user_id=enrollment_obj.user_id)
replicate_model(UserProfile.save, user_profile, enrollment_obj.user_id) replicate_model(UserProfile.save, user_profile, enrollment_obj.user_id)
# @receiver(post_delete, sender=CourseEnrollment) # @receiver(post_delete, sender=CourseEnrollment)
def replicate_enrollment_delete(sender, **kwargs): def replicate_enrollment_delete(sender, **kwargs):
enrollment_obj = kwargs['instance'] enrollment_obj = kwargs['instance']
return replicate_model(CourseEnrollment.delete, enrollment_obj, enrollment_obj.user_id) return replicate_model(CourseEnrollment.delete, enrollment_obj, enrollment_obj.user_id)
# @receiver(post_save, sender=UserProfile) # @receiver(post_save, sender=UserProfile)
def replicate_userprofile_save(sender, **kwargs): def replicate_userprofile_save(sender, **kwargs):
"""We just updated the UserProfile (say an update to the name), so push that """We just updated the UserProfile (say an update to the name), so push that
...@@ -339,6 +347,7 @@ USER_FIELDS_TO_COPY = ["id", "username", "first_name", "last_name", "email", ...@@ -339,6 +347,7 @@ USER_FIELDS_TO_COPY = ["id", "username", "first_name", "last_name", "email",
"password", "is_staff", "is_active", "is_superuser", "password", "is_staff", "is_active", "is_superuser",
"last_login", "date_joined"] "last_login", "date_joined"]
def replicate_user(portal_user, course_db_name): def replicate_user(portal_user, course_db_name):
"""Replicate a User to the correct Course DB. This is more complicated than """Replicate a User to the correct Course DB. This is more complicated than
it should be because Askbot extends the auth_user table and adds its own it should be because Askbot extends the auth_user table and adds its own
...@@ -362,6 +371,7 @@ def replicate_user(portal_user, course_db_name): ...@@ -362,6 +371,7 @@ def replicate_user(portal_user, course_db_name):
course_user.save(using=course_db_name) course_user.save(using=course_db_name)
unmark(course_user) unmark(course_user)
def replicate_model(model_method, instance, user_id): def replicate_model(model_method, instance, user_id):
""" """
model_method is the model action that we want replicated. For instance, model_method is the model action that we want replicated. For instance,
...@@ -379,8 +389,10 @@ def replicate_model(model_method, instance, user_id): ...@@ -379,8 +389,10 @@ def replicate_model(model_method, instance, user_id):
model_method(instance, using=db_name) model_method(instance, using=db_name)
unmark(instance) unmark(instance)
######### Replication Helpers ######### ######### Replication Helpers #########
def is_valid_course_id(course_id): def is_valid_course_id(course_id):
"""Right now, the only database that's not a course database is 'default'. """Right now, the only database that's not a course database is 'default'.
I had nicer checking in here originally -- it would scan the courses that I had nicer checking in here originally -- it would scan the courses that
...@@ -390,23 +402,27 @@ def is_valid_course_id(course_id): ...@@ -390,23 +402,27 @@ def is_valid_course_id(course_id):
""" """
return course_id != 'default' return course_id != 'default'
def is_portal(): def is_portal():
"""Are we in the portal pool? Only Portal servers are allowed to replicate """Are we in the portal pool? Only Portal servers are allowed to replicate
their changes. For now, only Portal servers see multiple DBs, so we use their changes. For now, only Portal servers see multiple DBs, so we use
that to decide.""" that to decide."""
return len(settings.DATABASES) > 1 return len(settings.DATABASES) > 1
def db_names_to_replicate_to(user_id): def db_names_to_replicate_to(user_id):
"""Return a list of DB names that this user_id is enrolled in.""" """Return a list of DB names that this user_id is enrolled in."""
return [c.course_id return [c.course_id
for c in CourseEnrollment.objects.filter(user_id=user_id) for c in CourseEnrollment.objects.filter(user_id=user_id)
if is_valid_course_id(c.course_id)] if is_valid_course_id(c.course_id)]
def marked_handled(instance): def marked_handled(instance):
"""Have we marked this instance as being handled to avoid infinite loops """Have we marked this instance as being handled to avoid infinite loops
caused by saving models in post_save hooks for the same models?""" caused by saving models in post_save hooks for the same models?"""
return hasattr(instance, '_do_not_copy_to_course_db') and instance._do_not_copy_to_course_db return hasattr(instance, '_do_not_copy_to_course_db') and instance._do_not_copy_to_course_db
def mark_handled(instance): def mark_handled(instance):
"""You have to mark your instance with this function or else we'll go into """You have to mark your instance with this function or else we'll go into
an infinite loop since we're putting listeners on Model saves/deletes and an infinite loop since we're putting listeners on Model saves/deletes and
...@@ -418,11 +434,13 @@ def mark_handled(instance): ...@@ -418,11 +434,13 @@ def mark_handled(instance):
""" """
instance._do_not_copy_to_course_db = True instance._do_not_copy_to_course_db = True
def unmark(instance): def unmark(instance):
"""If we don't unmark a model after we do replication, then consecutive """If we don't unmark a model after we do replication, then consecutive
save() calls won't be properly replicated.""" save() calls won't be properly replicated."""
instance._do_not_copy_to_course_db = False instance._do_not_copy_to_course_db = False
def should_replicate(instance): def should_replicate(instance):
"""Should this instance be replicated? We need to be a Portal server and """Should this instance be replicated? We need to be a Portal server and
the instance has to not have been marked_handled.""" the instance has to not have been marked_handled."""
......
...@@ -38,6 +38,7 @@ log = logging.getLogger("mitx.courseware") ...@@ -38,6 +38,7 @@ log = logging.getLogger("mitx.courseware")
template_imports = {'urllib': urllib} template_imports = {'urllib': urllib}
@ensure_csrf_cookie @ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True) @cache_control(no_cache=True, no_store=True, must_revalidate=True)
def instructor_dashboard(request, course_id): def instructor_dashboard(request, course_id):
...@@ -51,29 +52,29 @@ def instructor_dashboard(request, course_id): ...@@ -51,29 +52,29 @@ def instructor_dashboard(request, course_id):
def escape(s): def escape(s):
"""escape HTML special characters in string""" """escape HTML special characters in string"""
return str(s).replace('<','&lt;').replace('>','&gt;') return str(s).replace('<', '&lt;').replace('>', '&gt;')
# assemble some course statistics for output to instructor # assemble some course statistics for output to instructor
datatable = {'header': ['Statistic','Value'], datatable = {'header': ['Statistic', 'Value'],
'title': 'Course Statistics At A Glance', 'title': 'Course Statistics At A Glance',
} }
data = [ ['# Enrolled' ,CourseEnrollment.objects.filter(course_id=course_id).count()] ] data = [['# Enrolled', CourseEnrollment.objects.filter(course_id=course_id).count()]]
data += compute_course_stats(course).items() data += compute_course_stats(course).items()
if request.user.is_staff: if request.user.is_staff:
data.append(['metadata', escape(str(course.metadata))]) data.append(['metadata', escape(str(course.metadata))])
datatable['data'] = data datatable['data'] = data
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=%s' % 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']:
writer.writerow(datarow) writer.writerow(datarow)
return response return response
def get_staff_group(course): def get_staff_group(course):
staffgrp = get_access_group_name(course,'staff') staffgrp = get_access_group_name(course, 'staff')
try: try:
group = Group.objects.get(name=staffgrp) group = Group.objects.get(name=staffgrp)
except Group.DoesNotExist: except Group.DoesNotExist:
...@@ -82,10 +83,10 @@ def instructor_dashboard(request, course_id): ...@@ -82,10 +83,10 @@ def instructor_dashboard(request, course_id):
return group return group
# process actions from form POST # process actions from form POST
action = request.POST.get('action','') action = request.POST.get('action', '')
if 'Reload' in action: if 'Reload' in action:
log.debug('reloading %s (%s)' % (course_id,course)) log.debug('reloading %s (%s)' % (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)
...@@ -93,7 +94,7 @@ def instructor_dashboard(request, course_id): ...@@ -93,7 +94,7 @@ def instructor_dashboard(request, course_id):
except Exception as err: except Exception as err:
msg += '<br/><p>Error: %s</p>' % escape(err) msg += '<br/><p>Error: %s</p>' % escape(err)
elif action=='Dump list of enrolled students': elif 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 %s' % course_id
...@@ -122,11 +123,11 @@ def instructor_dashboard(request, course_id): ...@@ -122,11 +123,11 @@ def instructor_dashboard(request, course_id):
msg += 'Staff group = %s' % group.name msg += 'Staff group = %s' % group.name
log.debug('staffgrp=%s' % group.name) log.debug('staffgrp=%s' % 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 %s' % course_id
elif action=='Add course staff': elif action == 'Add course staff':
uname = request.POST['staffuser'] uname = request.POST['staffuser']
try: try:
user = User.objects.get(username=uname) user = User.objects.get(username=uname)
...@@ -135,11 +136,11 @@ def instructor_dashboard(request, course_id): ...@@ -135,11 +136,11 @@ def instructor_dashboard(request, course_id):
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 %s to staff group = %s</font>' % (user, group.name)
log.debug('staffgrp=%s' % group.name) log.debug('staffgrp=%s' % group.name)
user.groups.add(group) user.groups.add(group)
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)
...@@ -148,21 +149,22 @@ def instructor_dashboard(request, course_id): ...@@ -148,21 +149,22 @@ def instructor_dashboard(request, course_id):
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 %s from staff group = %s</font>' % (user, group.name)
log.debug('staffgrp=%s' % group.name) log.debug('staffgrp=%s' % group.name)
user.groups.remove(group) user.groups.remove(group)
# For now, mostly a static page # For now, mostly a static page
context = {'course': course, context = {'course': course,
'staff_access': True, 'staff_access': True,
'admin_access' : request.user.is_staff, 'admin_access': request.user.is_staff,
'instructor_access' : instructor_access, 'instructor_access': instructor_access,
'datatable' : datatable, 'datatable': datatable,
'msg' : msg, 'msg': msg,
} }
return render_to_response('courseware/instructor_dashboard.html', context) return render_to_response('courseware/instructor_dashboard.html', context)
def get_student_grade_summary_data(request, course, course_id, get_grades=True, get_raw_scores=False): def get_student_grade_summary_data(request, course, course_id, get_grades=True, get_raw_scores=False):
''' '''
Return data arrays with student identity and grades for specified course. Return data arrays with student identity and grades for specified course.
...@@ -183,9 +185,10 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True, ...@@ -183,9 +185,10 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True,
''' '''
enrolled_students = User.objects.filter(courseenrollment__course_id=course_id).order_by('username') enrolled_students = User.objects.filter(courseenrollment__course_id=course_id).order_by('username')
header = ['ID', 'Username','Full Name','edX email','External email'] header = ['ID', 'Username', 'Full Name', 'edX email', 'External email']
if get_grades: if get_grades:
gradeset = grades.grade(enrolled_students[0], request, course, keep_raw_scores=get_raw_scores) # just to construct the header # just to construct the header
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 %s gradeset %s' % (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']]
...@@ -214,6 +217,7 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True, ...@@ -214,6 +217,7 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True,
datatable['data'] = data datatable['data'] = data
return datatable return datatable
@cache_control(no_cache=True, no_store=True, must_revalidate=True) @cache_control(no_cache=True, no_store=True, must_revalidate=True)
def gradebook(request, course_id): def gradebook(request, course_id):
""" """
...@@ -240,7 +244,7 @@ def gradebook(request, course_id): ...@@ -240,7 +244,7 @@ def gradebook(request, course_id):
'course': course, 'course': course,
'course_id': course_id, 'course_id': course_id,
# Checked above # Checked above
'staff_access': True,}) 'staff_access': True, })
@cache_control(no_cache=True, no_store=True, must_revalidate=True) @cache_control(no_cache=True, no_store=True, must_revalidate=True)
...@@ -250,9 +254,10 @@ def grade_summary(request, course_id): ...@@ -250,9 +254,10 @@ def grade_summary(request, course_id):
# For now, just a static page # For now, just a static page
context = {'course': course, context = {'course': course,
'staff_access': True,} 'staff_access': True, }
return render_to_response('courseware/grade_summary.html', context) return render_to_response('courseware/grade_summary.html', context)
@ensure_csrf_cookie @ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True) @cache_control(no_cache=True, no_store=True, must_revalidate=True)
def enroll_students(request, course_id): def enroll_students(request, course_id):
...@@ -269,7 +274,7 @@ def enroll_students(request, course_id): ...@@ -269,7 +274,7 @@ def enroll_students(request, course_id):
''' '''
course = get_course_with_access(request.user, course_id, 'staff') course = get_course_with_access(request.user, course_id, 'staff')
existing_students = [ce.user.email for ce in CourseEnrollment.objects.filter(course_id = course_id)] existing_students = [ce.user.email for ce in CourseEnrollment.objects.filter(course_id=course_id)]
if 'new_students' in request.POST: if 'new_students' in request.POST:
new_students = request.POST['new_students'].split('\n') new_students = request.POST['new_students'].split('\n')
...@@ -282,20 +287,21 @@ def enroll_students(request, course_id): ...@@ -282,20 +287,21 @@ def enroll_students(request, course_id):
for student in new_students: for student in new_students:
try: try:
nce = CourseEnrollment(user=User.objects.get(email = student), course_id = course_id) nce = CourseEnrollment(user=User.objects.get(email=student), course_id=course_id)
nce.save() nce.save()
added_students.append(student) added_students.append(student)
except: except:
rejected_students.append(student) rejected_students.append(student)
return render_to_response("enroll_students.html", {'course':course_id, return render_to_response("enroll_students.html", {'course': course_id,
'existing_students': existing_students, 'existing_students': existing_students,
'added_students': added_students, 'added_students': added_students,
'rejected_students': rejected_students, 'rejected_students': rejected_students,
'debug':new_students}) 'debug': new_students})
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def compute_course_stats(course): def compute_course_stats(course):
''' '''
Compute course statistics, including number of problems, videos, html. Compute course statistics, including number of problems, videos, html.
...@@ -308,8 +314,6 @@ def compute_course_stats(course): ...@@ -308,8 +314,6 @@ def compute_course_stats(course):
counts = defaultdict(int) counts = defaultdict(int)
print "hello world"
def walk(module): def walk(module):
children = module.get_children() children = module.get_children()
if not children: if not children:
...@@ -317,14 +321,8 @@ def compute_course_stats(course): ...@@ -317,14 +321,8 @@ def compute_course_stats(course):
counts[category] += 1 counts[category] += 1
return return
for c in children: for c in children:
# print c.__class__.__name__
walk(c) walk(c)
walk(course) walk(course)
print "course %s counts=%s" % (course.display_name,counts)
stats = dict(counts) # number of each kind of module stats = dict(counts) # number of each kind of module
return stats return stats
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