Commit a7536773 by Victor Shnayder

Merge pull request #1047 from MITx/feature/jarv/cert-commands

Django commands for certificates
parents 07cbb9f0 ca2a8ba4
# -*- coding: utf-8 -*-
from django.core.management.base import BaseCommand
from certificates.models import certificate_status_for_student
from certificates.queue import XQueueCertInterface
from django.contrib.auth.models import User
from student.models import UserProfile
class Command(BaseCommand):
help = """
Looks for names that have unicode characters
and queues them up for a certificate request
"""
def handle(self, *args, **options):
# TODO this is only temporary for CS169 certs
course_id = 'BerkeleyX/CS169.1x/2012_Fall'
enrolled_students = User.objects.filter(
courseenrollment__course_id=course_id).prefetch_related(
"groups").order_by('username')
xq = XQueueCertInterface()
print "Looking for unusual names.."
for student in enrolled_students:
if certificate_status_for_student(
student, course_id)['status'] == 'unavailable':
continue
name = UserProfile.objects.get(user=student).name
for c in name:
if ord(c) >= 0x200:
ret = xq.add_cert(student, course_id)
if ret == 'generating':
print 'generating for {0}'.format(student)
break
from django.core.management.base import BaseCommand
from certificates.models import GeneratedCertificate
from django.contrib.auth.models import User
from optparse import make_option
from django.conf import settings
from xmodule.course_module import CourseDescriptor
from xmodule.modulestore.django import modulestore
from django.db.models import Count
class Command(BaseCommand):
help = """
Generate a certificate status report for all courses that have ended.
This command does not do anything other than report the current
certificate status.
unavailable - A student is not eligible for a certificate.
generating - A request has been made to generate a certificate,
but it has not been generated yet.
regenerating - A request has been made to regenerate a certificate,
but it has not been generated yet.
deleting - A request has been made to delete a certificate.
deleted - The certificate has been deleted.
downloadable - The certificate is available for download.
notpassing - The student was graded but is not passing
"""
option_list = BaseCommand.option_list + (
make_option('-c', '--course',
metavar='COURSE_ID',
dest='course',
default=None,
help='Only generate for COURSE_ID'),
)
def _ended_courses(self):
for course_id in [course # all courses in COURSE_LISTINGS
for sub in settings.COURSE_LISTINGS
for course in settings.COURSE_LISTINGS[sub]]:
course_loc = CourseDescriptor.id_to_location(course_id)
course = modulestore().get_instance(course_id, course_loc)
if course.has_ended():
yield course_id
def handle(self, *args, **options):
# Find all courses that have ended
if options['course']:
ended_courses = [options['course']]
else:
ended_courses = self._ended_courses()
cert_data = {}
for course_id in ended_courses:
# find students who are enrolled
print "Looking up certificate states for {0}".format(course_id)
enrolled_students = User.objects.filter(
courseenrollment__course_id=course_id).prefetch_related(
"groups").order_by('username')
unavailable_count = enrolled_students.count() - \
GeneratedCertificate.objects.filter(
course_id__exact=course_id).count()
cert_data[course_id] = {'enrolled': enrolled_students.count()}
cert_data[course_id].update({'unavailable': unavailable_count})
tallies = GeneratedCertificate.objects.values(
'status').annotate(dcount=Count('status'))
cert_data[course_id].update(
{status['status']: status['dcount']
for status in tallies})
# all states we have seen far all courses
status_headings = set(
[status for course in cert_data
for status in cert_data[course]])
# print the heading for the report
print "{:>20}".format("course ID"),
print ' '.join(["{:>12}".format(heading)
for heading in status_headings])
# print the report
for course_id in cert_data:
print "{0:>20}".format(course_id[0:18]),
for heading in status_headings:
if heading in cert_data[course_id]:
print "{:>12}".format(cert_data[course_id][heading]),
else:
print " " * 12,
print
......@@ -2,29 +2,92 @@ from django.core.management.base import BaseCommand
from certificates.models import certificate_status_for_student
from certificates.queue import XQueueCertInterface
from django.contrib.auth.models import User
from optparse import make_option
from django.conf import settings
from xmodule.course_module import CourseDescriptor
from xmodule.modulestore.django import modulestore
from certificates.models import CertificateStatuses
import datetime
class Command(BaseCommand):
help = """
Find all students that have need certificates
and put certificate requests on the queue
Find all students that need certificates
for courses that have finished and
put their cert requests on the queue
This is only for BerkeleyX/CS169.1x/2012_Fall
Use the --noop option to test without actually
putting certificates on the queue to be generated.
"""
option_list = BaseCommand.option_list + (
make_option('-n', '--noop',
action='store_true',
dest='noop',
default=False,
help="Don't add certificate requests to the queue"),
make_option('-c', '--course',
metavar='COURSE_ID',
dest='course',
default=False,
help='Grade and generate certificates for a specific course'),
)
def handle(self, *args, **options):
# TODO This is only temporary for CS169 certs
# Will only generate a certificate if the current
# status is in this state
VALID_STATUSES = [
CertificateStatuses.unavailable
]
# Print update after this many students
course_id = 'BerkeleyX/CS169.1x/2012_Fall'
STATUS_INTERVAL = 500
if options['course']:
ended_courses = [options['course']]
else:
# Find all courses that have ended
ended_courses = []
for course_id in [course # all courses in COURSE_LISTINGS
for sub in settings.COURSE_LISTINGS
for course in settings.COURSE_LISTINGS[sub]]:
course_loc = CourseDescriptor.id_to_location(course_id)
course = modulestore().get_instance(course_id, course_loc)
if course.has_ended():
ended_courses.append(course_id)
for course_id in ended_courses:
print "Fetching enrolled students for {0}".format(course_id)
enrolled_students = User.objects.filter(
courseenrollment__course_id=course_id).prefetch_related(
"groups").order_by('username')
xq = XQueueCertInterface()
total = enrolled_students.count()
count = 0
start = datetime.datetime.now()
for student in 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()
if certificate_status_for_student(
student, course_id)['status'] == 'unavailable':
student, course_id)['status'] in VALID_STATUSES:
if not options['noop']:
# Add the certificate request to the queue
ret = xq.add_cert(student, course_id)
if ret == 'generating':
print 'generating for {0}'.format(student)
print '{0} - {1}'.format(student, ret)
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