Files
edx-platform/common/djangoapps/student/management/commands/get_grades.py
John Jarvis 6ba85765e7 pep8
2013-08-21 15:15:13 -04:00

111 lines
4.5 KiB
Python

from courseware import grades, courses
from certificates.models import GeneratedCertificate
from django.test.client import RequestFactory
from django.core.management.base import BaseCommand, CommandError
import os
from django.contrib.auth.models import User
from optparse import make_option
import datetime
from django.core.handlers.base import BaseHandler
import csv
class RequestMock(RequestFactory):
def request(self, **request):
"Construct a generic request object."
request = RequestFactory.request(self, **request)
handler = BaseHandler()
handler.load_middleware()
for middleware_method in handler._request_middleware:
if middleware_method(request):
raise Exception("Couldn't create request mock object - "
"request middleware returned a response")
return request
class Command(BaseCommand):
help = """
Generate a list of grades for all students
that are enrolled in a course.
CSV will include the following:
- username
- email
- grade in the certificate table if it exists
- computed grade
- grade breakdown
Outputs grades to a csv file.
Example:
sudo -u www-data SERVICE_VARIANT=lms /opt/edx/bin/django-admin.py get_grades \
-c MITx/Chi6.00intro/A_Taste_of_Python_Programming -o /tmp/20130813-6.00x.csv \
--settings=lms.envs.aws --pythonpath=/opt/wwc/edx-platform
"""
option_list = BaseCommand.option_list + (
make_option('-c', '--course',
metavar='COURSE_ID',
dest='course',
default=False,
help='Course ID for grade distribution'),
make_option('-o', '--output',
metavar='FILE',
dest='output',
default=False,
help='Filename for grade output'))
def handle(self, *args, **options):
if os.path.exists(options['output']):
raise CommandError("File {0} already exists".format(
options['output']))
STATUS_INTERVAL = 100
course_id = options['course']
print "Fetching enrolled students for {0}".format(course_id)
enrolled_students = User.objects.filter(
courseenrollment__course_id=course_id)
factory = RequestMock()
request = factory.get('/')
total = enrolled_students.count()
print "Total enrolled: {0}".format(total)
course = courses.get_course_by_id(course_id)
total = enrolled_students.count()
start = datetime.datetime.now()
rows = []
header = None
print "Fetching certificate data"
cert_grades = {cert.user.username: cert.grade
for cert in list(GeneratedCertificate.objects.filter(
course_id=course_id).prefetch_related('user'))}
print "Grading students"
for count, student in enumerate(enrolled_students):
count += 1
if count % STATUS_INTERVAL == 0:
# Print a status update with an approximation of
# how much time is left based on how long the last
# interval took
diff = datetime.datetime.now() - start
timeleft = diff * (total - count) / STATUS_INTERVAL
hours, remainder = divmod(timeleft.seconds, 3600)
minutes, seconds = divmod(remainder, 60)
print "{0}/{1} completed ~{2:02}:{3:02}m remaining".format(
count, total, hours, minutes)
start = datetime.datetime.now()
request.user = student
grade = grades.grade(student, request, course)
if not header:
header = [section['label'] for section in grade[u'section_breakdown']]
rows.append(["email", "username", "certificate-grade", "grade"] + header)
percents = {section['label']: section['percent'] for section in grade[u'section_breakdown']}
row_percents = [percents[label] for label in header]
if student.username in cert_grades:
rows.append([student.email, student.username, cert_grades[student.username], grade['percent']] + row_percents)
else:
rows.append([student.email, student.username, "N/A", grade['percent']] + row_percents)
with open(options['output'], 'wb') as f:
writer = csv.writer(f)
writer.writerows(rows)