def viewlotteryprefs(self, request, tl, one, two, module, extra, prog):
        context = {}
        context['student'] = request.user

        priority_classids = set()
        uniquified_flags = []
        priority_flags = StudentRegistration.valid_objects().filter(user=request.user, section__parent_class__parent_program=prog, relationship__name='Priority/1')
        for flag in priority_flags:
            if flag.section.id not in priority_classids:
                priority_classids.add(flag.section.id)
                uniquified_flags.append(flag)
        context['priority'] = uniquified_flags
        if priority_flags.count() == 0:
            context['pempty'] = True
        else: context['pempty'] = False

        interested_classids = set()
        uniquified_interested = []
        interested = StudentRegistration.valid_objects().filter(user=request.user, section__parent_class__parent_program=prog, relationship__name='Interested')
        for flag in interested:
            if flag.section.id not in interested_classids:
                interested_classids.add(flag.section.id)
                uniquified_interested.append(flag)
        context['interested' ] = uniquified_interested
        if interested.count() == 0:
            context['iempty'] = True
        else: context['iempty'] = False

        return render_to_response(self.baseDir()+'view_lottery_prefs.html', request, context)
    def students(self, QObject = False):

        Enrolled = Q(studentregistration__relationship__name='Enrolled')
        Par = Q(studentregistration__section__parent_class__parent_program=self.program)
        Unexpired = nest_Q(StudentRegistration.is_valid_qobject(), 'studentregistration')

        # Force Django to generate two subqueries without joining SRs to SSIs,
        # as efficiently as possible since it's still a big query.
        sr_ids = StudentRegistration.valid_objects().filter(
            section__parent_class__parent_program=self.program
        ).values('user').distinct()
        ssi_ids = StudentSubjectInterest.valid_objects().filter(
            subject__parent_program=self.program).values('user').distinct()
        any_reg_q = Q(id__in = sr_ids) | Q(id__in = ssi_ids)

        qobjects = {
            'enrolled': Enrolled & Par & Unexpired,
            'classreg': any_reg_q,
        }

        if QObject:
            return qobjects
        else:
            return {k: ESPUser.objects.filter(v).distinct()
                    for k, v in qobjects.iteritems()}
Exemplo n.º 3
0
    def test_json_view(self):
        self.client.login(username='******', password='******')
        r = self.client.get('/onsite/' + self.program.url + '/unenroll_status')
        data = json.loads(r.content)

        self.assertGreaterEqual(len(data['student_timeslots']), 20)
        self.assertGreater(len(data['section_timeslots']), 0)
        self.assertGreater(len(data['enrollments']), 0)

        for student_id, ts_id in data['student_timeslots'].items():
            self.assertTrue(self.timeslots.filter(id=ts_id).exists())
            self.assertTrue(StudentRegistration.valid_objects().filter(
                user=student_id, section__meeting_times=ts_id).exists())
            self.assertFalse(
                Record.objects.filter(event='attended',
                                      program=self.program,
                                      user=student_id).exists())

        for section_id, ts_id in data['section_timeslots'].items():
            self.assertTrue(self.timeslots.filter(id=ts_id).exists())
            sec = ClassSection.objects.get(id=section_id)
            self.assertTrue(sec.meeting_times.filter(id=ts_id).exists())
            self.assertTrue(StudentRegistration.valid_objects().filter(
                section=section_id).exists())

        for sr_id, (user_id, section_id) in data['enrollments'].items():
            sr = StudentRegistration.objects.get(id=sr_id)
            self.assertEqual(sr.user_id, user_id)
            self.assertEqual(sr.section_id, section_id)
            self.assertIn(str(user_id), data['student_timeslots'])
            self.assertIn(str(section_id), data['section_timeslots'])
Exemplo n.º 4
0
 def lottery_preferences_legacy(self, request, prog):
     # DEPRECATED: see comments in lottery_preferences method
     sections = list(prog.sections().values('id'))
     sections_interested = StudentRegistration.valid_objects().filter(
         relationship__name='Interested',
         user=request.user,
         section__parent_class__parent_program=prog).select_related(
             'section__id').values_list('section__id',
                                        flat=True).distinct()
     sections_priority = StudentRegistration.valid_objects().filter(
         relationship__name='Priority/1',
         user=request.user,
         section__parent_class__parent_program=prog).select_related(
             'section__id').values_list('section__id',
                                        flat=True).distinct()
     for item in sections:
         if item['id'] in sections_interested:
             item['lottery_interested'] = True
         else:
             item['lottery_interested'] = False
         if item['id'] in sections_priority:
             item['lottery_priority'] = True
         else:
             item['lottery_priority'] = False
     return {'sections': sections}
    def test_json_view(self):
        self.client.login(username='******', password='******')
        r = self.client.get('/onsite/' + self.program.url + '/unenroll_status')
        data = json.loads(r.content)

        self.assertGreaterEqual(len(data['student_timeslots']), 20)
        self.assertGreater(len(data['section_timeslots']), 0)
        self.assertGreater(len(data['enrollments']), 0)

        for student_id, ts_id in data['student_timeslots'].items():
            self.assertTrue(self.timeslots.filter(id=ts_id).exists())
            self.assertTrue(StudentRegistration.valid_objects().filter(
                user=student_id, section__meeting_times=ts_id).exists())
            self.assertFalse(Record.objects.filter(
                event='attended', program=self.program,
                user=student_id).exists())

        for section_id, ts_id in data['section_timeslots'].items():
            self.assertTrue(self.timeslots.filter(id=ts_id).exists())
            sec = ClassSection.objects.get(id=section_id)
            self.assertTrue(sec.meeting_times.filter(id=ts_id).exists())
            self.assertTrue(StudentRegistration.valid_objects().filter(
                section=section_id).exists())

        for sr_id, (user_id, section_id) in data['enrollments'].items():
            sr = StudentRegistration.objects.get(id=sr_id)
            self.assertEqual(sr.user_id, user_id)
            self.assertEqual(sr.section_id, section_id)
            self.assertIn(str(user_id), data['student_timeslots'])
            self.assertIn(str(section_id), data['section_timeslots'])
Exemplo n.º 6
0
    def students(self, QObject=False):

        Enrolled = Q(studentregistration__relationship__name='Enrolled')
        Par = Q(studentregistration__section__parent_class__parent_program=self
                .program)
        Unexpired = nest_Q(StudentRegistration.is_valid_qobject(),
                           'studentregistration')

        # Force Django to generate two subqueries without joining SRs to SSIs,
        # as efficiently as possible since it's still a big query.
        sr_ids = StudentRegistration.valid_objects().filter(
            section__parent_class__parent_program=self.program).values(
                'user').distinct()
        ssi_ids = StudentSubjectInterest.valid_objects().filter(
            subject__parent_program=self.program).values('user').distinct()
        any_reg_q = Q(id__in=sr_ids) | Q(id__in=ssi_ids)

        qobjects = {
            'enrolled': Enrolled & Par & Unexpired,
            'classreg': any_reg_q,
        }

        if QObject:
            return qobjects
        else:
            return {
                k: ESPUser.objects.filter(v).distinct()
                for k, v in qobjects.iteritems()
            }
Exemplo n.º 7
0
    def viewlotteryprefs(self, request, tl, one, two, module, extra, prog):
        context = {}
        context['student'] = request.user
        context['program'] = prog

        priority_classids = set()
        uniquified_flags = []
        priority_flags = StudentRegistration.valid_objects().filter(user=request.user, section__parent_class__parent_program=prog, relationship__name='Priority/1')
        for flag in priority_flags:
            if flag.section.id not in priority_classids:
                priority_classids.add(flag.section.id)
                uniquified_flags.append(flag)
        context['priority'] = uniquified_flags
        if priority_flags.count() == 0:
            context['pempty'] = True
        else: context['pempty'] = False

        interested_classids = set()
        uniquified_interested = []
        interested = StudentRegistration.valid_objects().filter(user=request.user, section__parent_class__parent_program=prog, relationship__name='Interested')
        for flag in interested:
            if flag.section.id not in interested_classids:
                interested_classids.add(flag.section.id)
                uniquified_interested.append(flag)
        context['interested' ] = uniquified_interested
        if interested.count() == 0:
            context['iempty'] = True
        else: context['iempty'] = False

        return render_to_response(self.baseDir()+'view_lottery_prefs.html', request, (prog, tl), context)
    def classchangerequest(self, request, tl, one, two, module, extra, prog):
        timeslots = prog.getTimeSlots()
        sections = prog.sections().filter(status=10, meeting_times__isnull=False).distinct()

        enrollments = {}
        for timeslot in timeslots:
            try:
                enrollments[timeslot] = ClassSubject.objects.get(nest_Q(StudentRegistration.is_valid_qobject(), 'sections__studentregistration'), sections__studentregistration__relationship__name="Enrolled", sections__studentregistration__user=request.user, sections__meeting_times=timeslot, parent_program=prog)
            except ClassSubject.DoesNotExist:
                enrollments[timeslot] = None

        context = {}
        context['timeslots'] = timeslots
        context['enrollments'] = enrollments
        context['user'] = request.user
        if 'success' in request.GET:
            context['success'] = True
        else:
            context['success'] = False

        if request.user.isStudent():
            sections_by_slot = dict([(timeslot,[(section, 1 == StudentRegistration.valid_objects().filter(user=context['user'], section=section, relationship__name="Request").count()) for section in sections if section.get_meeting_times()[0] == timeslot and section.parent_class.grade_min <= request.user.getGrade(prog) <= section.parent_class.grade_max and section.parent_class not in enrollments.values() and ESPUser.getRankInClass(request.user, section.parent_class) in (5,10)]) for timeslot in timeslots])
        else:
            sections_by_slot = dict([(timeslot,[(section, False) for section in sections if section.get_meeting_times()[0] == timeslot]) for timeslot in timeslots])

        fields = {}
        for i, timeslot in enumerate(sections_by_slot.keys()):
            choices = [('0', "I'm happy with my current enrollment.")]
            initial = '0'
            for section in sections_by_slot[timeslot]:
                choices.append((section[0].emailcode(), section[0].emailcode()+": "+section[0].title()))
                if section[1]:
                    initial = section[0].emailcode()
            fields['timeslot_'+str(i+1)] = forms.ChoiceField(label="Timeslot "+str(i+1)+" ("+timeslot.pretty_time()+")", choices=choices, initial=initial)

        form = type('ClassChangeRequestForm', (forms.Form,), fields)
        context['form'] = form()
        if request.method == "POST":
            old_requests = StudentRegistration.valid_objects().filter(user=context['user'], section__parent_class__parent_program=prog, relationship__name="Request")
            for r in old_requests:
                r.expire()
            form = form(request.POST)
            if form.is_valid():
                for value in form.cleaned_data.values():
                    section = None
                    for s in sections:
                        if s.emailcode() == value:
                            section = s
                            break
                    if not section:
                        continue
                    r = StudentRegistration.valid_objects().get_or_create(user=context['user'], section=section, relationship=RegistrationType.objects.get_or_create(name="Request", category="student")[0])[0]
                    r.save()

                return HttpResponseRedirect(request.path.rstrip('/')+'/?success')
        else:
            return render_to_response(self.baseDir() + 'classchangerequest.html', request, context)
Exemplo n.º 9
0
    def __init__(self, program, **kwargs):
        """ Set constant parameters for class changes. """

        assert isinstance(program,(Program,int))
        self.program = program
        if isinstance(program,int):
            self.program = Program.objects.get(id=program)
        print self.program
        iscorrect = raw_input("Is this the correct program (y/[n])? ")
        assert (iscorrect.lower() == 'y' or iscorrect.lower() == 'yes')
        self.now = datetime.now()
        self.options = ClassChangeController.default_options.copy()
        self.options.update(kwargs)
        self.students_not_checked_in = []
        self.deadline = self.now
        if 'deadline' in self.options.keys():
            self.deadline = self.options['deadline']

        self.Q_SR_NOW = nest_Q(StudentRegistration.is_valid_qobject(self.now), 'studentregistration')
        self.Q_SR_PROG = Q(studentregistration__section__parent_class__parent_program=self.program, studentregistration__section__meeting_times__isnull=False) & self.Q_SR_NOW
        self.Q_SR_REQ = Q(studentregistration__relationship__name="Request") & self.Q_SR_PROG
        self.Q_NOW = StudentRegistration.is_valid_qobject(self.now)
        self.Q_PROG = Q(section__parent_class__parent_program=self.program, section__meeting_times__isnull=False) & self.Q_NOW
        self.Q_REQ = Q(relationship__name="Request") & self.Q_PROG

        self.students = ESPUser.objects.filter(self.Q_SR_REQ).order_by('id').distinct()
        if 'students_not_checked_in' in self.options.keys() and isinstance(self.options['students_not_checked_in'],QuerySet):
            self.students_not_checked_in = list(self.options['students_not_checked_in'].values_list('id',flat=True).distinct())
        else:
            self.students_not_checked_in = list(self.students.exclude(id__in=self.program.students()['attended']).values_list('id',flat=True).distinct())

        self.priority_limit = self.program.priorityLimit()
        self._init_Q_objects()
        self.sections = self.program.sections().filter(status__gt=0, parent_class__status__gt=0, meeting_times__isnull=False).order_by('id').select_related('parent_class','parent_class__parent_program').distinct()
        if not self.options['use_closed_classes']:
            self.sections = self.sections.filter(registration_status=0).distinct()
        self.timeslots = self.program.getTimeSlots().order_by('id').distinct()
        self.num_timeslots = len(self.timeslots)
        self.num_students = len(self.students)
        self.num_sections = len(self.sections)






        numpy.random.seed(self.now.microsecond)

        self.initialize()

        if self.options['stats_display']:
            logger.info('Initialized lottery assignment for %d students, %d sections, %d timeslots', self.num_students, self.num_sections, self.num_timeslots)
Exemplo n.º 10
0
    def __init__(self, program, **kwargs):
        """ Set constant parameters for class changes. """

        assert isinstance(program,(Program,int))
        self.program = program
        if isinstance(program,int):
            self.program = Program.objects.get(id=program)
        print self.program
        iscorrect = raw_input("Is this the correct program (y/[n])? ")
        assert (iscorrect.lower() == 'y' or iscorrect.lower() == 'yes')
        self.now = datetime.now()
        self.options = ClassChangeController.default_options.copy()
        self.options.update(kwargs)
        self.students_not_checked_in = []
        self.deadline = self.now
        if 'deadline' in self.options.keys():
            self.deadline = self.options['deadline']
        self.Q_SR_NOW = nest_Q(StudentRegistration.is_valid_qobject(self.now), 'studentregistration')
        self.Q_SR_PROG = Q(studentregistration__section__parent_class__parent_program=self.program, studentregistration__section__meeting_times__isnull=False) & self.Q_SR_NOW
        self.Q_SR_REQ = Q(studentregistration__relationship__name="Request") & self.Q_SR_PROG
        self.Q_NOW = StudentRegistration.is_valid_qobject(self.now)
        self.Q_PROG = Q(section__parent_class__parent_program=self.program, section__meeting_times__isnull=False) & self.Q_NOW
        self.Q_REQ = Q(relationship__name="Request") & self.Q_PROG
        self.students = ESPUser.objects.filter(self.Q_SR_REQ).order_by('id').distinct()
        if 'students_not_checked_in' in self.options.keys() and isinstance(self.options['students_not_checked_in'],QuerySet):
            self.students_not_checked_in = list(self.options['students_not_checked_in'].values_list('id',flat=True).distinct())
        else:
            self.students_not_checked_in = list(self.students.exclude(id__in=self.program.students()['attended']).values_list('id',flat=True).distinct())
        self.priority_limit = self.program.priorityLimit()
        self._init_Q_objects()
        self.sections = self.program.sections().filter(status__gt=0, parent_class__status__gt=0, meeting_times__isnull=False).order_by('id').select_related('parent_class','parent_class__parent_program','meeting_times').distinct()
        if not self.options['use_closed_classes']:
            self.sections = self.sections.filter(registration_status=0).distinct()
        self.timeslots = self.program.getTimeSlots().order_by('id').distinct()
        self.num_timeslots = len(self.timeslots)
        self.num_students = len(self.students)
        self.num_sections = len(self.sections)






        numpy.random.seed(self.now.microsecond)

        self.initialize()

        if self.options['stats_display']:
            logger.info('Initialized lottery assignment for %d students, %d sections, %d timeslots', self.num_students, self.num_sections, self.num_timeslots)
 def lottery_preferences_legacy(self, request, prog):
     # DEPRECATED: see comments in lottery_preferences method
     sections = list(prog.sections().values('id'))
     sections_interested = StudentRegistration.valid_objects().filter(relationship__name='Interested', user=request.user, section__parent_class__parent_program=prog).select_related('section__id').values_list('section__id', flat=True).distinct()
     sections_priority = StudentRegistration.valid_objects().filter(relationship__name='Priority/1', user=request.user, section__parent_class__parent_program=prog).select_related('section__id').values_list('section__id', flat=True).distinct()
     for item in sections:
         if item['id'] in sections_interested:
             item['lottery_interested'] = True
         else:
             item['lottery_interested'] = False
         if item['id'] in sections_priority:
             item['lottery_priority'] = True
         else:
             item['lottery_priority'] = False
     return {'sections': sections}
Exemplo n.º 12
0
    def save_assignments(self, debug_display=False, try_mailman=False):
        """ Store lottery assignments in the database once they have been computed.
            This is a fairly time consuming step compared to computing the assignments. """

        self.clear_saved_assignments()

        assignments = numpy.nonzero(self.student_sections)
        student_ids = self.student_ids[assignments[0]]
        section_ids = self.section_ids[assignments[1]]

        assert (student_ids.shape == section_ids.shape)

        relationship, created = RegistrationType.objects.get_or_create(
            name='Enrolled')
        self.now = datetime.now(
        )  # The time that all the registrations start at, in case all lottery registrations need to be manually reverted later
        StudentRegistration.objects.bulk_create([
            StudentRegistration(user_id=student_ids[i],
                                section_id=section_ids[i],
                                relationship=relationship,
                                start_date=self.now)
            for i in range(student_ids.shape[0])
        ])
        print "StudentRegistration enrollments all created to start at %s" % self.now
        if debug_display:
            print 'Created %d registrations' % student_ids.shape[0]

        #As mailman doesn't work, disable for now.
        if try_mailman:
            self.update_mailman_lists()
Exemplo n.º 13
0
    def getSchedule(program, student):

        schedule = """
Student schedule for %s:

 Time               | Class                   | Room""" % student.name()

        regs = StudentRegistration.valid_objects().filter(
            user=student,
            section__parent_class__parent_program=program,
            relationship__name='Accepted')
        classes = [x.section.parent_class for x in regs]

        # now we sort them by time/title
        classes.sort()

        for cls in classes:
            rooms = cls.prettyrooms()
            if len(rooms) == 0:
                rooms = 'N/A'
            else:
                rooms = ", ".join(rooms)

            schedule += """
%s|%s|%s""" % (",".join(
                cls.friendly_times()).ljust(20), cls.title.ljust(25), rooms)

        return schedule
 def num_users_enrolled(self, prog):
     # Querying for SRs and then extracting the users saves us joining the
     # users table.
     return StudentRegistration.valid_objects().filter(
         section__parent_class__parent_program=prog,
         relationship__name='Enrolled'
     ).values_list('user').distinct().count()
Exemplo n.º 15
0
 def num_users_enrolled(self, prog):
     # Querying for SRs and then extracting the users saves us joining the
     # users table.
     return StudentRegistration.valid_objects().filter(
         section__parent_class__parent_program=prog,
         relationship__name='Enrolled').values_list(
             'user').distinct().count()
    def getSchedule(program, student):

        schedule = u"""
Student schedule for %s:

 Time               | Class                   | Room""" % student.name()


        regs = StudentRegistration.valid_objects().filter(user=student, section__parent_class__parent_program=program, relationship__name='Accepted')
        classes = [x.section.parent_class for x in regs]

        # now we sort them by time/title
        classes.sort()

        for cls in classes:
            rooms = cls.prettyrooms()
            if len(rooms) == 0:
                rooms = u'N/A'
            else:
                rooms = u", ".join(rooms)

            schedule += u"""
%s|%s|%s""" % (u",".join(cls.friendly_times()).ljust(20),
               cls.title.ljust(25),
               rooms)

        return schedule
Exemplo n.º 17
0
    def clear_saved_assignments(self, delete=False):
        """ Expire/delete all previous StudentRegistration enrollments associated with the program. """

        old_registrations = StudentRegistration.objects.filter(section__parent_class__parent_program=self.program, relationship__name='Enrolled')
        if delete:
            old_registrations.delete()
        else:
            old_registrations.filter(StudentRegistration.is_valid_qobject()).update(end_date=datetime.now())
Exemplo n.º 18
0
 def students(self, QObject=False):
     q = Q(studentregistration__section__parent_class__parent_program=self.
           program) & nest_Q(StudentRegistration.is_valid_qobject(),
                             'studentregistration')
     if QObject:
         return {'lotteried_students': q}
     else:
         return {'lotteried_students': ESPUser.objects.filter(q).distinct()}
Exemplo n.º 19
0
def lsr_submit_HSSP(request, program, priority_limit, data):  # temporary function. will merge the two later -jmoldow 05/31
    
    classes_flagged = [set() for i in range(0,priority_limit+1)] # 1-indexed
    sections_by_block = [defaultdict(set) for i in range(0,priority_limit+1)] # 1-indexed - sections_by_block[i][block] is a set of classes that were given priority i in timeblock block. This should hopefully be a set of size 0 or 1.
    
    for section_id, (priority, block_id) in data.iteritems():
        section_id = int(section_id)
        priority = int(priority)
        block_id = int(block_id)
        classes_flagged[0].add(section_id)
        classes_flagged[priority].add(section_id)
        sections_by_block[priority][block_id].add(section_id)

    errors = []
    
    for i in range(1, priority_limit+1):
        for block in sections_by_block[i].keys():
            if len(sections_by_block[i][block]) > 1:
                errors.append({"text": "Can't flag two classes with the same priority at the same time!", "cls_sections": list(sections_by_block[i][block]), "block": block, "priority": i, "doubled_priority": True})
    
    if len(errors): 
        return HttpResponse(json.dumps(errors), mimetype='application/json')

    reg_priority = [(None,None)] + [RegistrationType.objects.get_or_create(name="Priority/"+str(i), category="student") for i in range(1,priority_limit+1)]
    reg_priority = [reg_priority[i][0] for i in range(0, priority_limit+1)] 
    
    allStudentRegistrations = StudentRegistration.valid_objects().filter(section__parent_class__parent_program=program, user=request.user)
    oldRegistrations = [] #[[] for i in range(0, priority_limit+1)] # 1-indexed for priority registrations, the 0-index is for interested registrations
    
    for i in range(1, priority_limit+1):
        oldRegistrations += [(oldRegistration, i) for oldRegistration in list(allStudentRegistrations.filter(relationship=reg_priority[i]).select_related(depth=3))]
    
    for (oldRegistration, priority) in oldRegistrations:
        if oldRegistration.section.id not in classes_flagged[0]:
            oldRegistration.expire()
            continue
        for i in range(1, priority_limit + 1):
            if oldRegistration.section.id in classes_flagged[i]:
                if i != priority:
                    oldRegistration.expire()
                elif i == priority:
                    classes_flagged[i].remove(oldRegistration.section.id)
                    classes_flagged[0].remove(oldRegistration.section.id)
                break
    
    flagworthy_sections = [None] + [ClassSection.objects.filter(id__in=classes_flagged[i]).select_related(depth=2).annotate(first_block=Min('meeting_times__start')) for i in range(1, priority_limit + 1)]
    
    for i in range(1, priority_limit + 1):
        for s in list(flagworthy_sections[i]):
            if not s.preregister_student(request.user, prereg_verb=reg_priority[i].name, overridefull=True):
                errors.append({"text": "Unable to add flagged class", "cls_sections": [s.id], "emailcode": s.emailcode(), "block": s.first_block, "flagged": True, "priority": i, "doubled_priority": False})

    if len(errors) != 0:
        s = StringIO()
        pprint(errors, s)
        mail_admins('Error in class reg', s.getvalue(), fail_silently=True)

    return HttpResponse(json.dumps(errors), mimetype='application/json')
Exemplo n.º 20
0
def lsr_submit_HSSP(request, program, priority_limit, data):  # temporary function. will merge the two later -jmoldow 05/31

    classes_flagged = [set() for i in range(0,priority_limit+1)] # 1-indexed
    sections_by_block = [defaultdict(set) for i in range(0,priority_limit+1)] # 1-indexed - sections_by_block[i][block] is a set of classes that were given priority i in timeblock block. This should hopefully be a set of size 0 or 1.

    for section_id, (priority, block_id) in data.iteritems():
        section_id = int(section_id)
        priority = int(priority)
        block_id = int(block_id)
        classes_flagged[0].add(section_id)
        classes_flagged[priority].add(section_id)
        sections_by_block[priority][block_id].add(section_id)

    errors = []

    for i in range(1, priority_limit+1):
        for block in sections_by_block[i].keys():
            if len(sections_by_block[i][block]) > 1:
                errors.append({"text": "Can't flag two classes with the same priority at the same time!", "cls_sections": list(sections_by_block[i][block]), "block": block, "priority": i, "doubled_priority": True})

    if len(errors):
        return HttpResponse(json.dumps(errors), content_type='application/json')

    reg_priority = [(None,None)] + [RegistrationType.objects.get_or_create(name="Priority/"+str(i), category="student") for i in range(1,priority_limit+1)]
    reg_priority = [reg_priority[i][0] for i in range(0, priority_limit+1)]

    allStudentRegistrations = StudentRegistration.valid_objects().filter(section__parent_class__parent_program=program, user=request.user)
    oldRegistrations = [] #[[] for i in range(0, priority_limit+1)] # 1-indexed for priority registrations, the 0-index is for interested registrations

    for i in range(1, priority_limit+1):
        oldRegistrations += [(oldRegistration, i) for oldRegistration in list(allStudentRegistrations.filter(relationship=reg_priority[i]))]

    for (oldRegistration, priority) in oldRegistrations:
        if oldRegistration.section.id not in classes_flagged[0]:
            oldRegistration.expire()
            continue
        for i in range(1, priority_limit + 1):
            if oldRegistration.section.id in classes_flagged[i]:
                if i != priority:
                    oldRegistration.expire()
                elif i == priority:
                    classes_flagged[i].remove(oldRegistration.section.id)
                    classes_flagged[0].remove(oldRegistration.section.id)
                break

    flagworthy_sections = [None] + [ClassSection.objects.filter(id__in=classes_flagged[i]).annotate(first_block=Min('meeting_times__start')) for i in range(1, priority_limit + 1)]

    for i in range(1, priority_limit + 1):
        for s in list(flagworthy_sections[i]):
            if not s.preregister_student(request.user, prereg_verb=reg_priority[i].name, overridefull=True):
                errors.append({"text": "Unable to add flagged class", "cls_sections": [s.id], "emailcode": s.emailcode(), "block": s.first_block, "flagged": True, "priority": i, "doubled_priority": False})

    if len(errors) != 0:
        s = StringIO()
        pprint(errors, s)
        mail_admins('Error in class reg', s.getvalue(), fail_silently=True)

    return HttpResponse(json.dumps(errors), content_type='application/json')
Exemplo n.º 21
0
 def enrollment_status(self, request, tl, one, two, module, extra, prog):
     resp = HttpResponse(mimetype='application/json')
     data = StudentRegistration.valid_objects().filter(
         section__status__gt=0,
         section__parent_class__status__gt=0,
         section__parent_class__parent_program=prog,
         relationship__name='Enrolled').values_list('user__id',
                                                    'section__id')
     simplejson.dump(list(data), resp)
     return resp
Exemplo n.º 22
0
 def load_data(self):
     lunch_registrations = list(StudentRegistration.valid_objects().filter(
         user=self.user,
         section__parent_class__category__category='Lunch',
         section__parent_class__parent_program=self.program))
     if len(lunch_registrations) > 0:
         section = lunch_registrations[0].section
         if len(section.get_meeting_times()) > 0:
             print 'Set initial to %s' % section.get_meeting_times()[0]
             self.initial['timeslot'] = section.get_meeting_times()[0].id
 def lottery_preferences_usepriority(self, request, prog):
     sections = list(prog.sections().values('id'))
     for i in range(1, prog.priorityLimit()+1, 1):
         priority_name = 'Priority/' + str(i)
         sections_priority = StudentRegistration.valid_objects().filter(relationship__name=priority_name, user=request.user, section__parent_class__parent_program=prog).select_related('section__id').values_list('section__id', flat=True).distinct()
         for item in sections:
             if item['id'] in sections_priority:
                 item[priority_name] = True
             #else:
             #   item['lottery_priority'] = False
     return {'sections': sections}
Exemplo n.º 24
0
    def unenroll_status(prog):
        """
        Assemble the data necessary to compute the set of enrollments to
        expire for a given combination of student first class times
        and section start times.

        Returns:
        enrollments: { enrollment id -> (user id, section id) }
        student_timeslots: { user id -> event id of first class timeslot }
        section_timeslots: { section id -> event id of first timeslot }

        """
        enrolled = RegistrationType.objects.get(name='Enrolled')

        sections = prog.sections().filter(
            status__gt=0, parent_class__status__gt=0)
        sections = sections.exclude(
            parent_class__category__category='Lunch')

        enrollments = StudentRegistration.valid_objects().filter(
            relationship=enrolled, section__in=sections)

        # students not checked in
        students = ESPUser.objects.filter(
            id__in=enrollments.values('user'))
        students = students.exclude(
            record__program=prog, record__event='attended')

        # enrollments for those students
        relevant = enrollments.filter(user__in=students).values_list(
            'id', 'user', 'section', 'section__meeting_times')
        relevant = relevant.order_by('section__meeting_times__start')

        section_timeslots = {}  # section -> starting timeslot id
        student_timeslots = {}  # student -> starting timeslot id
        enrollments = {}        # id -> (student, section)
        for id, student, section, ts in relevant:
            if ts is None:
                continue

            if section not in section_timeslots:
                section_timeslots[section] = ts

            if student not in student_timeslots:
                student_timeslots[student] = ts

            enrollments[id] = (student, section)

        return {
            'section_timeslots': section_timeslots,
            'student_timeslots': student_timeslots,
            'enrollments': enrollments
        }
Exemplo n.º 25
0
    def review_students(self, request, tl, one, two, module, extra, prog):
        """ Show a roster of the students in the class, allowing the administrators
        to accept students into the program based on the teachers' reviews and the
        students' applications. """

        try:
            cls = ClassSubject.objects.get(id=extra)
        except ClassSubject.DoesNotExist:
            raise ESPError(False), 'Cannot find class.'

        if not request.user.canEdit(cls):
            raise ESPError(False), 'You cannot edit class "%s"' % cls

        #   Fetch any student even remotely related to the class.
        students_dict = cls.students_dict()
        students = []
        for key in students_dict:
            students += students_dict[key]

        students = filter(
            lambda x: x.studentapplication_set.filter(program=self.program).
            count() > 0, students)

        for student in students:
            student.added_class = student.studentregistration_set.filter(
                section__parent_class=cls)[0].start_date
            try:
                student.app = student.studentapplication_set.get(
                    program=self.program)
            except:
                student.app = None

            if student.app:
                reviews = student.app.reviews.all()
            else:
                reviews = []

            if StudentRegistration.valid_objects().filter(
                    user=student,
                    section__parent_class=cls,
                    relationship__name='Accepted').count() > 0:
                student.status = 'Accepted'
            else:
                student.status = 'Not accepted'

        students = list(students)
        students.sort(key=lambda x: x.last_name)

        return render_to_response(self.baseDir() + 'roster.html', request, {
            'class': cls,
            'students': students,
            'program': prog
        })
Exemplo n.º 26
0
 def num_users_with_lottery(self, prog):
     # Past empirical observation has shown that doing the union in SQL is
     # much, much slower for unknown reasons; it also means we would have to
     # query over the users table, so this saves us joining that table.
     users_with_ssis = set(StudentSubjectInterest.valid_objects().filter(
         subject__parent_program=prog).values_list('user').distinct())
     users_with_srs = set(StudentRegistration.valid_objects().filter(
         Q(relationship__name='Interested')
         | Q(relationship__name__contains='Priority/'),
         section__parent_class__parent_program=prog).values_list(
             'user').distinct())
     return len(users_with_ssis | users_with_srs)
Exemplo n.º 27
0
 def get_schedule_json(self, request, tl, one, two, module, extra, prog):
     resp = HttpResponse(content_type='application/json')
     result = {'user': None, 'user_grade': 0, 'sections': [], 'messages': []}
     try:
         result['user'] = int(request.GET['user'])
     except:
         result['messages'].append('Error: no user specified.')
     if result['user']:
         result['user_grade'] = ESPUser.objects.get(id=result['user']).getGrade(program=prog)
         result['sections'] = list(ClassSection.objects.filter(nest_Q(StudentRegistration.is_valid_qobject(), 'studentregistration'), status__gt=0, parent_class__status__gt=0, parent_class__parent_program=prog, studentregistration__relationship__name='Enrolled', studentregistration__user__id=result['user']).values_list('id', flat=True).distinct())
     json.dump(result, resp)
     return resp
 def get_schedule_json(self, request, tl, one, two, module, extra, prog):
     resp = HttpResponse(content_type='application/json')
     result = {'user': None, 'user_grade': 0, 'sections': [], 'messages': []}
     try:
         result['user'] = int(request.GET['user'])
     except:
         result['messages'].append('Error: no user specified.')
     if result['user']:
         result['user_grade'] = ESPUser.objects.get(id=result['user']).getGrade(program=prog)
         result['sections'] = list(ClassSection.objects.filter(nest_Q(StudentRegistration.is_valid_qobject(), 'studentregistration'), status__gt=0, parent_class__status__gt=0, parent_class__parent_program=prog, studentregistration__relationship__name='Enrolled', studentregistration__user__id=result['user']).values_list('id', flat=True).distinct())
     json.dump(result, resp)
     return resp
    def catalog_registered_classes_json(self, request, tl, one, two, module, extra, prog, timeslot=None):
        reg_bits = StudentRegistration.valid_objects().filter(user=request.user, section__parent_class__parent_program=prog).select_related()

        reg_bits_data = [
            { 'user': b.user.username,
              'section_id': b.section_id,
              'type': b.relationship.name
              }
            for b in reg_bits ]

        resp = HttpResponse(content_type='application/json')
        json.dump(reg_bits_data, resp)
        return resp
    def test_submit(self):
        self.client.login(username='******', password='******')
        r = self.client.get('/onsite/' + self.program.url + '/unenroll_status')
        data = json.loads(r.content)
        enrollment_ids = data['enrollments'].keys()

        r = self.client.post('/onsite/' + self.program.url + '/unenroll_students', {'selected_enrollments': ','.join(enrollment_ids)})
        self.assertContains(r, 'Expired %d student registrations' % len(enrollment_ids))
        self.assertContains(r, ', '.join(enrollment_ids))

        enrollments = StudentRegistration.objects.filter(id__in=enrollment_ids)
        self.assertFalse(enrollments.filter(StudentRegistration.is_valid_qobject()).exists())

        enrollments.update(end_date=None)
Exemplo n.º 31
0
 def load_data(self):
     lunch_registrations = StudentRegistration.valid_objects().filter(
         user=self.user,
         section__parent_class__category__category='Lunch',
         section__parent_class__parent_program=self.program).select_related(
             'section').prefetch_related('section__meeting_times')
     lunch_registrations = [
         lunch_registration for lunch_registration in lunch_registrations
         if list(lunch_registration.section.meeting_times.all())
         [0].start.day == self.day.day
     ]
     if len(lunch_registrations) > 0:
         section = lunch_registrations[0].section
         if len(section.get_meeting_times()) > 0:
             self.initial['timeslot'] = section.get_meeting_times()[0].id
 def num_users_with_lottery(self, prog):
     # Past empirical observation has shown that doing the union in SQL is
     # much, much slower for unknown reasons; it also means we would have to
     # query over the users table, so this saves us joining that table.
     users_with_ssis = set(
         StudentSubjectInterest.valid_objects()
         .filter(subject__parent_program=prog)
         .values_list('user').distinct())
     users_with_srs = set(
         StudentRegistration.valid_objects()
         .filter(
             Q(relationship__name='Interested') |
             Q(relationship__name__contains='Priority/'),
             section__parent_class__parent_program=prog)
         .values_list('user').distinct())
     return len(users_with_ssis | users_with_srs)
Exemplo n.º 33
0
 def lottery_preferences_usepriority(self, request, prog):
     sections = list(prog.sections().values('id'))
     for i in range(1, prog.priorityLimit() + 1, 1):
         priority_name = 'Priority/' + str(i)
         sections_priority = StudentRegistration.valid_objects().filter(
             relationship__name=priority_name,
             user=request.user,
             section__parent_class__parent_program=prog).select_related(
                 'section__id').values_list('section__id',
                                            flat=True).distinct()
         for item in sections:
             if item['id'] in sections_priority:
                 item[priority_name] = True
             #else:
             #   item['lottery_priority'] = False
     return {'sections': sections}
    def review_students(self, request, tl, one, two, module, extra, prog):
        """ Show a roster of the students in the class, allowing the administrators
        to accept students into the program based on the teachers' reviews and the
        students' applications. """

        try:
            cls = ClassSubject.objects.get(id = extra)
        except ClassSubject.DoesNotExist:
            raise ESPError('Cannot find class.', log=False)

        if not request.user.canEdit(cls):
            raise ESPError('You cannot edit class "%s"' % cls, log=False)

        #   Fetch any student even remotely related to the class.
        students_dict = cls.students_dict()
        students = []
        for key in students_dict:
            students += students_dict[key]

        students = filter(lambda x: x.studentapplication_set.filter(program=self.program).count() > 0, students)

        for student in students:
            student.added_class = student.studentregistration_set.filter(section__parent_class=cls)[0].start_date
            try:
                student.app = student.studentapplication_set.get(program = self.program)
            except:
                student.app = None

            if student.app:
                reviews = student.app.reviews.all()
            else:
                reviews = []

            if StudentRegistration.valid_objects().filter(user=student, section__parent_class=cls, relationship__name='Accepted').count() > 0:
                student.status = 'Accepted'
            else:
                student.status = 'Not accepted'

        students = list(students)
        students.sort(key=lambda x: x.last_name)

        return render_to_response(self.baseDir()+'roster.html',
                                  request,
                                  {'class': cls,
                                   'students':students, 'program': prog})
Exemplo n.º 35
0
    def test_submit(self):
        self.client.login(username='******', password='******')
        r = self.client.get('/onsite/' + self.program.url + '/unenroll_status')
        data = json.loads(r.content)
        enrollment_ids = data['enrollments'].keys()

        r = self.client.post(
            '/onsite/' + self.program.url + '/unenroll_students',
            {'selected_enrollments': ','.join(enrollment_ids)})
        self.assertContains(
            r, 'Expired %d student registrations' % len(enrollment_ids))
        self.assertContains(r, ', '.join(enrollment_ids))

        enrollments = StudentRegistration.objects.filter(id__in=enrollment_ids)
        self.assertFalse(
            enrollments.filter(
                StudentRegistration.is_valid_qobject()).exists())

        enrollments.update(end_date=None)
Exemplo n.º 36
0
 def students(self, QObject=False):
     q_sr = Q(
         studentregistration__section__parent_class__parent_program=self.
         program) & nest_Q(StudentRegistration.is_valid_qobject(),
                           'studentregistration')
     q_ssi = Q(studentsubjectinterest__subject__parent_program=self.program
               ) & nest_Q(StudentSubjectInterest.is_valid_qobject(),
                          'studentsubjectinterest')
     if QObject:
         return {
             'twophase_star_students': q_ssi,
             'twophase_priority_students': q_sr
         }
     else:
         return {
             'twophase_star_students':
             ESPUser.objects.filter(q_ssi).distinct(),
             'twophase_priority_students':
             ESPUser.objects.filter(q_sr).distinct()
         }
Exemplo n.º 37
0
    def catalog_registered_classes_json(self,
                                        request,
                                        tl,
                                        one,
                                        two,
                                        module,
                                        extra,
                                        prog,
                                        timeslot=None):
        reg_bits = StudentRegistration.valid_objects().filter(
            user=request.user,
            section__parent_class__parent_program=prog).select_related()

        reg_bits_data = [{
            'user': b.user.username,
            'section_id': b.section_id,
            'type': b.relationship.name
        } for b in reg_bits]

        resp = HttpResponse(content_type='application/json')
        json.dump(reg_bits_data, resp)
        return resp
Exemplo n.º 38
0
    def save_assignments(self, try_mailman=True):
        """ Store lottery assignments in the database once they have been computed.
            This is a fairly time consuming step compared to computing the assignments. """

        self.clear_saved_assignments()

        assignments = numpy.nonzero(self.student_sections)
        student_ids = self.student_ids[assignments[0]]
        section_ids = self.section_ids[assignments[1]]

        assert(student_ids.shape == section_ids.shape)

        relationship, created = RegistrationType.objects.get_or_create(name='Enrolled')
        self.now = datetime.now()   # The time that all the registrations start at, in case all lottery registrations need to be manually reverted later
        StudentRegistration.objects.bulk_create([StudentRegistration(user_id=student_ids[i], section_id=section_ids[i], relationship=relationship, start_date=self.now) for i in range(student_ids.shape[0])])
        if self.options['stats_display']:
            logger.info("StudentRegistration enrollments all created to start at %s", self.now)
            logger.info('Created %d registrations', student_ids.shape[0])

        #As mailman has sometimes not worked in the past,
        #leave the option to disable.
        if try_mailman:
            self.update_mailman_lists()
Exemplo n.º 39
0
    def students(self, QObject=False):
        from django.db.models import Q

        Enrolled = Q(studentregistration__relationship__name='Enrolled')
        Par = Q(studentregistration__section__parent_class__parent_program=self
                .program)
        Unexpired = nest_Q(StudentRegistration.is_valid_qobject(),
                           'studentregistration')

        if QObject:
            retVal = {
                'enrolled': self.getQForUser(Enrolled & Par & Unexpired),
                'classreg': self.getQForUser(Par & Unexpired)
            }
        else:
            retVal = {
                'enrolled':
                ESPUser.objects.filter(Enrolled & Par & Unexpired).distinct(),
                'classreg':
                ESPUser.objects.filter(Par & Unexpired).distinct()
            }

        allowed_student_types = Tag.getTag("allowed_student_types",
                                           target=self.program)
        if allowed_student_types:
            allowed_student_types = allowed_student_types.split(",")
            for stutype in allowed_student_types:
                GroupName = Q(groups__name=stutype)
                if QObject:
                    retVal[stutype] = self.getQForUser(Par & Unexpired & Reg
                                                       & VerbName & VerbParent)
                else:
                    retVal[stutype] = ESPUser.objects.filter(
                        Par & Unexpired & Reg & GroupName).distinct()

        return retVal
Exemplo n.º 40
0
    def review_students(self, request, tl, one, two, module, extra, prog):
        try:
            cls = ClassSubject.objects.get(id = extra)
        except ClassSubject.DoesNotExist:
            raise ESPError('Cannot find class.', log=False)

        if not request.user.canEdit(cls):
            raise ESPError('You cannot edit class "%s"' % cls, log=False)

        #   Fetch any student even remotely related to the class.
        students_dict = cls.students_dict()
        students = []
        for key in students_dict:
            students += students_dict[key]

        for student in students:
            now = datetime.now()
            student.added_class = StudentRegistration.valid_objects().filter(section__parent_class = cls, user = student)[0].start_date
            try:
                student.app = student.studentapplication_set.get(program = self.program)
            except:
                student.app = None

            if student.app:
                reviews = student.app.reviews.all().filter(reviewer=request.user, score__isnull=False)
                questions = student.app.questions.all().filter(subject=cls)
            else:
                reviews = []
                questions = []

            if len(reviews) > 0:
                student.app_reviewed = reviews[0]
            else:
                student.app_reviewed = None

            student.app_completed = False
            for i in questions:
                for j in i.studentappresponse_set.all():
                    if j.complete:
                        student.app_completed = True

        students = list(students)
        students.sort(lambda x,y: cmp(x.added_class,y.added_class))

        if 'prev' in request.GET:
            prev_id = int(request.GET.get('prev'))
            prev = students[0]
            current = None
            for current in students[1:]:
                if prev.id == prev_id and current.app_completed:
                    from django.shortcuts import redirect
                    url = "/%s/%s/%s/review_student/%s/?student=%s" % (tl, one, two, extra, current.id)
                    return redirect(url)
                if prev.id != prev_id:
                    prev = current


        return render_to_response(self.baseDir()+'roster.html',
                                  request,
                                  {'class': cls,
                                   'students':students})
Exemplo n.º 41
0
    def review_student(self, request, tl, one, two, module, extra, prog):
        scrmi = prog.studentclassregmoduleinfo
        reg_nodes = scrmi.reg_verbs()

        try:
            cls = ClassSubject.objects.get(id = extra)
        except ClassSubject.DoesNotExist:
            raise ESPError('Cannot find class.', log=False)

        if not request.user.canEdit(cls):
            raise ESPError('You cannot edit class "%s"' % cls, log=False)

        student = request.GET.get('student',None)
        if not student:
            student = request.POST.get('student','')

        try:
            student = ESPUser.objects.get(id = int(student))
        except ESPUser.DoesNotExist:
            raise ESPError('Cannot find student, %s' % student, log=False)

        not_registered = not StudentRegistration.valid_objects().filter(section__parent_class = cls, user = student).exists()
        if not_registered:
            raise ESPError('Student not a student of this class.', log=False)

        try:
            student.app = student.studentapplication_set.get(program = self.program)
        except:
            student.app = None
            raise ESPError('Error: Student did not start an application.', log=False)

        student.added_class = StudentRegistration.valid_objects().filter(section__parent_class = cls, user = student)[0].start_date

        teacher_reviews = student.app.reviews.all().filter(reviewer=request.user)
        if teacher_reviews.count() > 0:
            this_review = teacher_reviews.order_by('id')[0]
        else:
            this_review = StudentAppReview(reviewer=request.user)
            this_review.save()
            student.app.reviews.add(this_review)

        if request.method == 'POST':
            form = this_review.get_form(request.POST)
            if form.is_valid():
                form.target.update(form)
                if 'submit_next' in request.POST or 'submit_return' in request.POST:
                    url = '/%s/%s/%s/review_students/%s/' % (tl, one, two, extra)
                    if 'submit_next' in request.POST:
                        url += '?prev=%s' % student.id
                    from django.shortcuts import redirect
                    return redirect(url) # self.review_students(request, tl, one, two, module, extra, prog)


        else:
            form = this_review.get_form()

        return render_to_response(self.baseDir()+'review.html',
                                  request,
                                  {'class': cls,
                                   'reviews': teacher_reviews,
                                  'program': prog,
                                   'student':student,
                                   'form': form})
Exemplo n.º 42
0
    def select_students(self, request, tl, one, two, module, extra, prog):
        #   Get preregistered and enrolled students
        try:
            sec = ClassSection.objects.get(id=extra)
        except (ValueError, ClassSection.DoesNotExist):
            raise ESPError(
                'Class section not found.  If you came from a link on our site, please notify the webmasters.',
                log=False)

        students_list = sec.students_prereg()

        if request.method == 'POST':
            #   Handle form submission
            #   result_strs = []
            data = request.POST.copy()
            sections_dict = {}
            for key in data:
                key_dir = key.split('_')
                if key_dir[0] == 'regstatus' and len(key_dir) == 3:
                    student_id = int(key_dir[1])
                    sec_id = int(key_dir[2])
                    if sec_id not in sections_dict:
                        sections_dict[sec_id] = [{
                            'id': student_id,
                            'status': data[key]
                        }]
                    else:
                        sections_dict[sec_id].append({
                            'id': student_id,
                            'status': data[key]
                        })

            for sec_id in sections_dict:
                sec = ClassSection.objects.get(id=sec_id)
                sec.cache['students'] = None
                sec.cache['num_students'] = None
                for item in sections_dict[sec_id]:
                    student = ESPUser.objects.get(id=item['id'])
                    ignore = False
                    value = item['status']
                    if value == 'enroll':
                        verb_name = 'Enrolled'
                    elif value == 'reject':
                        verb_name = 'Rejected'
                    else:
                        ignore = True

                    if not ignore:
                        rel = RegistrationType.get_map(
                            include=['Enrolled', 'Rejected'],
                            category='student')[verb_name]
                        other_regs = sec.getRegistrations(student).filter(
                            relationship__name__in=['Enrolled', 'Rejected'])
                        found = False
                        for reg in other_regs:
                            if not found and reg.relationship == rel:
                                found = True
                            else:
                                reg.expire()

                        if not found:
                            new_reg = StudentRegistration(user=student,
                                                          relationship=rel,
                                                          section=sec)
                            new_reg.save()

        #   Jazz up this information a little
        #Not having much luck with query count/performance when selecting related parent_class and parent_class__category
        #Creating a lookup dict instead to strip out duplicate ClassSubject instances

        student_regs = StudentRegistration.valid_objects().filter(user__in=students_list) \
                       .order_by('start_date').select_related('section','user','relationship')
        student_regs = student_regs.filter(
            section__parent_class__parent_program=self.program)

        student_sections_dict = defaultdict(set)
        student_reg_dict = defaultdict(set)

        #need a unique set of parent_class ids
        #creating lookup dicts to avoid hitting database(was not solved with
        #select_related or prefecth_related
        parent_class_id_set = set()
        sections = set()
        for reg in student_regs:
            student_sections_dict[reg.user].add(reg.section)
            display_name = reg.relationship.displayName or reg.relationship.name
            sections.add(reg.section)
            parent_class_id_set.add(reg.section.parent_class_id)
            student_reg_dict['%i_%i' % (
                reg.user.id,
                reg.section.id,
            )].add(display_name)

        subjects = ClassSubject.objects.filter(
            id__in=parent_class_id_set).select_related('category')
        subject_categories_dict = dict([(s.id, (s, s.category))
                                        for s in subjects])

        for student in students_list:
            student.bits = student_reg_dict['%i_%i' % (
                student.id,
                sec.id,
            )]
            #this is a bit of a problem because it produces the side affect of application
            #creation if not found
            student.app = student.getApplication(self.program, False)
            student.other_classes = []
            for section in student_sections_dict[student]:
                parent_class, category = subject_categories_dict.get(
                    section.parent_class_id)
                regtypes = student_reg_dict['%i_%i' % (
                    student.id,
                    section.id,
                )]

                section_row = (section, regtypes, parent_class, category)
                student.other_classes.append(section_row)
            preregs = sec.getRegistrations(student).exclude(
                relationship__name__in=['Enrolled', 'Rejected'])

            if preregs.count() != 0:
                student.added_class = preregs[0].start_date
            if 'Enrolled' in student.bits:
                student.enrolled = True
            elif 'Rejected' in student.bits:
                student.rejected = True

        #   Detect if there is an application module

        from esp.program.modules.handlers.studentjunctionappmodule import StudentJunctionAppModule
        has_app_module = False
        for module in prog.getModules():
            if isinstance(module, StudentJunctionAppModule):
                has_app_module = True

        return render_to_response(
            self.baseDir() + 'select_students.html', request, {
                'has_app_module': has_app_module,
                'prog': prog,
                'sec': sec,
                'students_list': students_list
            })
Exemplo n.º 43
0
    def select_students(self, request, tl, one, two, module, extra, prog):
        #   Get preregistered and enrolled students
        try:
            sec = ClassSection.objects.filter(id=extra)[0]
        except:
            raise ESPError(
                False
            ), 'Class section not found.  If you came from a link on our site, please notify the webmasters.'

        students_list = sec.students_prereg()

        if request.method == 'POST':
            #   Handle form submission
            #   result_strs = []
            data = request.POST.copy()
            sections_dict = {}
            for key in data:
                key_dir = key.split('_')
                if key_dir[0] == 'regstatus' and len(key_dir) == 3:
                    student_id = int(key_dir[1])
                    sec_id = int(key_dir[2])
                    if sec_id not in sections_dict:
                        sections_dict[sec_id] = [{
                            'id': student_id,
                            'status': data[key]
                        }]
                    else:
                        sections_dict[sec_id].append({
                            'id': student_id,
                            'status': data[key]
                        })

            for sec_id in sections_dict:
                sec = ClassSection.objects.get(id=sec_id)
                sec.cache['students'] = None
                sec.cache['num_students'] = None
                for item in sections_dict[sec_id]:
                    student = ESPUser(User.objects.get(id=item['id']))
                    ignore = False
                    value = item['status']
                    if value == 'enroll':
                        verb_name = 'Enrolled'
                    elif value == 'reject':
                        verb_name = 'Rejected'
                    else:
                        ignore = True

                    if not ignore:
                        rel = RegistrationType.get_map(
                            include=['Enrolled', 'Rejected'],
                            category='student')[verb_name]
                        other_regs = sec.getRegistrations(student).filter(
                            relationship__name__in=['Enrolled', 'Rejected'])
                        found = False
                        for reg in other_regs:
                            if not found and reg.relationship == rel:
                                found = True
                            else:
                                reg.expire()
                            #   result_strs.append('Expired: %s' % bit)
                        if not found:
                            new_reg = StudentRegistration(user=student,
                                                          relationship=rel,
                                                          section=sec)
                            new_reg.save()

        #   Jazz up this information a little
        for student in students_list:
            student.bits = sec.getRegVerbs(student)
            student.app = student.getApplication(self.program, False)
            student.other_classes = [
                (sec2, sec2.getRegVerbs(student))
                for sec2 in student.getSections(self.program).exclude(
                    id=sec.id)
            ]
            preregs = sec.getRegistrations(student).exclude(
                relationship__name__in=['Enrolled', 'Rejected'])
            if preregs.count() != 0:
                student.added_class = preregs[0].start_date
            if 'Enrolled' in student.bits:
                student.enrolled = True
            elif 'Rejected' in student.bits:
                student.rejected = True

        #   Detect if there is an application module
        from esp.program.modules.handlers.studentjunctionappmodule import StudentJunctionAppModule
        has_app_module = False
        for module in prog.getModules():
            if isinstance(module, StudentJunctionAppModule):
                has_app_module = True

        return render_to_response(
            self.baseDir() + 'select_students.html', request, {
                'has_app_module': has_app_module,
                'prog': prog,
                'sec': sec,
                'students_list': students_list
            })
 def num_prefs(self, prog):
     num_srs = StudentRegistration.valid_objects().filter(
         section__parent_class__parent_program=prog).count()
     return num_srs + self.num_ssis(prog)
 def students(self, QObject = False):
     q = Q(studentregistration__section__parent_class__parent_program=self.program) & nest_Q(StudentRegistration.is_valid_qobject(), 'studentregistration')
     if QObject:
         return {'lotteried_students': q}
     else:
         return {'lotteried_students': ESPUser.objects.filter(q).distinct()}
    def save_priorities(self, request, tl, one, two, module, extra, prog):
        """
        Saves the priority preferences for student registration phase 2.
        """
        if not 'json_data' in request.POST:
            return HttpResponseBadRequest('JSON data not included in request.')
        try:
            json_data = json.loads(request.POST['json_data'])
        except ValueError:
            return HttpResponseBadRequest('JSON data mis-formatted.')
        try:
            [timeslot_id] = json_data.keys()
        except ValueError:
            return HttpResponseBadRequest('JSON data mis-formatted.')
        if not isinstance(json_data[timeslot_id], dict):
            return HttpResponseBadRequest('JSON data mis-formatted.')

        timeslot = Event.objects.get(pk=timeslot_id)
        priorities = json_data[timeslot_id]
        for rel_index, cls_id in priorities.items():
            rel_name = 'Priority/%s' % rel_index
            rel = RegistrationType.objects.get(name=rel_name, category='student')

            # Pull up any registrations that exist (including expired ones)
            srs = StudentRegistration.objects.annotate(
                Min('section__meeting_times__start'))
            srs = srs.filter(
                user=request.user,
                section__parent_class__parent_program=prog,
                section__meeting_times__start__min=timeslot.start,
                relationship=rel)

            if cls_id == '':
                # Blank: nothing selected, expire existing registrations
                for sr in srs:
                    sr.expire()
                continue

            cls_id = int(cls_id)
            sec = ClassSection.objects.annotate(Min('meeting_times__start'))
            try:
                sec = sec.get(parent_class=cls_id,
                              parent_class__parent_program=prog,
                              meeting_times__start__min=timeslot.start)
            except (ClassSection.DoesNotExist,
                    ClassSection.MultipleObjectsReturned):
                # XXX: what if a class has multiple sections in a timeblock?
                logger.warning("Could not save priority for class %s in "
                               "timeblock %s", cls_id, timeslot_id)
                continue
            # sanity checks
            if (not sec.status > 0 or not sec.parent_class.status > 0):
                logger.warning("Class '%s' was not approved.  Not letting "
                               "user '%s' register.", sec, request.user)
            if (not sec.parent_class.grade_min <= request.user.getGrade(prog)
                or not sec.parent_class.grade_max >= request.user.getGrade(prog)):
                logger.warning("User '%s' not in class grade range; not "
                               "letting them register.", request.user)
                continue

            if not srs.exists():
                # Create a new registration
                sr = StudentRegistration(
                    user=request.user,
                    relationship=rel)
            else:
                # Pull the first StudentRegistration, expire the others
                for sr in srs[1:]:
                    sr.expire()
                sr = srs[0]

            # Modify as needed to ensure the section is correct and
            # expiration date is valid
            if sr.section_id is None or sr.section.parent_class.id != cls_id:
                sr.section = sec
            sr.unexpire(save=False)
            sr.save()

        return self.goToCore(tl)
Exemplo n.º 47
0
    def initialize(self):
        """ Gather all of the information needed to run the lottery assignment.
            This includes:
            -   Students' interest (priority and interested bits)
            -   Class schedules and capacities
            -   Timeslots (incl. lunch periods for each day)
        """

        self.interest = numpy.zeros((self.num_students, self.num_sections),
                                    dtype=numpy.bool)
        self.priority = numpy.zeros((self.num_students, self.num_sections),
                                    dtype=numpy.bool)
        self.section_schedules = numpy.zeros(
            (self.num_sections, self.num_timeslots), dtype=numpy.bool)
        self.section_capacities = numpy.zeros((self.num_sections, ),
                                              dtype=numpy.uint32)
        self.section_overlap = numpy.zeros(
            (self.num_sections, self.num_sections), dtype=numpy.bool)

        # One array to keep track of the utility of each student
        # (defined as hours of interested class + 1.5*hours of priority classes)
        # and the other arrary to keep track of student weigths (defined as # of classes signed up for)
        self.student_utility_weights = numpy.zeros((self.num_students, ),
                                                   dtype=numpy.float)
        self.student_utilities = numpy.zeros((self.num_students, ),
                                             dtype=numpy.float)

        #   Get student, section, timeslot IDs and prepare lookup table
        (self.student_ids, self.student_indices) = self.get_ids_and_indices(
            self.program.students()['lotteried_students'])
        (self.section_ids, self.section_indices) = self.get_ids_and_indices(
            self.program.sections().filter(status__gt=0,
                                           registration_status=0))
        (self.timeslot_ids, self.timeslot_indices) = self.get_ids_and_indices(
            self.program.getTimeSlots())

        #   Get IDs of timeslots allocated to lunch by day
        #   (note: requires that this is constant across days)
        self.lunch_schedule = numpy.zeros((self.num_timeslots, ))
        lunch_timeslots = Event.objects.filter(
            meeting_times__parent_class__parent_program=self.program,
            meeting_times__parent_class__category__category='Lunch').order_by(
                'start').distinct()
        #   Note: this code should not be necessary once lunch-constraints branch is merged (provides Program.dates())
        dates = []
        for ts in self.program.getTimeSlots():
            ts_day = date(ts.start.year, ts.start.month, ts.start.day)
            if ts_day not in dates:
                dates.append(ts_day)
        lunch_by_day = [[] for x in dates]
        ts_count = 0
        for ts in lunch_timeslots:
            d = date(ts.start.year, ts.start.month, ts.start.day)
            lunch_by_day[dates.index(d)].append(ts.id)
            self.lunch_schedule[self.timeslot_indices[ts.id]] = True
        for i in range(len(lunch_by_day)):
            if len(lunch_by_day[i]) > ts_count:
                ts_count = len(lunch_by_day[i])
        self.lunch_timeslots = numpy.zeros((len(lunch_by_day), ts_count),
                                           dtype=numpy.int32)
        for i in range(len(lunch_by_day)):
            self.lunch_timeslots[i, :len(lunch_by_day[i])] = numpy.array(
                lunch_by_day[i])

        #   Populate interest matrix
        interest_regs = StudentRegistration.valid_objects().filter(
            section__parent_class__parent_program=self.program,
            relationship__name='Interested').values_list(
                'user__id', 'section__id').distinct()
        ira = numpy.array(interest_regs, dtype=numpy.uint32)
        self.interest[self.student_indices[ira[:, 0]],
                      self.section_indices[ira[:, 1]]] = True

        #   Populate priority matrix
        priority_regs = StudentRegistration.valid_objects().filter(
            section__parent_class__parent_program=self.program,
            relationship__name='Priority/1').values_list(
                'user__id', 'section__id').distinct()
        pra = numpy.array(priority_regs, dtype=numpy.uint32)
        self.priority[self.student_indices[pra[:, 0]],
                      self.section_indices[pra[:, 1]]] = True

        #   Set student utility weights. Counts number of classes that students selected. Used only for computing the overall_utility stat
        #   NOTE: Uses fixed (interest + priority) formula, needs attention when multiple priority levels are merged.
        self.student_utility_weights = numpy.sum(
            self.interest.astype(float), 1) + numpy.sum(
                self.priority.astype(float), 1)

        #   Populate section schedule
        section_times = numpy.array(self.program.sections().filter(
            status__gt=0, registration_status=0).filter(
                meeting_times__id__isnull=False).distinct().values_list(
                    'id', 'meeting_times__id'))
        self.section_schedules[self.section_indices[section_times[:, 0]],
                               self.timeslot_indices[section_times[:,
                                                                   1]]] = True

        #   Populate section overlap matrix
        parent_classes = numpy.array(self.program.sections().filter(
            status__gt=0, registration_status=0).order_by('id').values_list(
                'parent_class__id', flat=True))
        for i in range(self.num_sections):
            group_ids = numpy.nonzero(parent_classes == parent_classes[i])[0]
            self.section_overlap[numpy.meshgrid(group_ids, group_ids)] = True

        #   Populate section grade limits
        self.section_grade_min = numpy.array(self.program.sections().filter(
            status__gt=0, registration_status=0).order_by('id').values_list(
                'parent_class__grade_min', flat=True),
                                             dtype=numpy.uint32)
        self.section_grade_max = numpy.array(self.program.sections().filter(
            status__gt=0, registration_status=0).order_by('id').values_list(
                'parent_class__grade_max', flat=True),
                                             dtype=numpy.uint32)

        #   Populate student grades; grade will be assumed to be 0 if not entered on profile
        self.student_grades = numpy.zeros((self.num_students, ))
        gradyear_pairs = numpy.array(RegistrationProfile.objects.filter(
            user__id__in=list(self.student_ids),
            most_recent_profile=True,
            student_info__graduation_year__isnull=False).values_list(
                'user__id', 'student_info__graduation_year'),
                                     dtype=numpy.uint32)
        self.student_grades[self.student_indices[
            gradyear_pairs[:, 0]]] = 12 + ESPUser.current_schoolyear(
            ) - gradyear_pairs[:, 1]

        #   Find section capacities (TODO: convert to single query)
        for sec in self.program.sections().filter(status__gt=0,
                                                  registration_status=0):
            self.section_capacities[self.section_indices[
                sec.id]] = sec.capacity

        # Populate section lengths (hours)
        self.section_lengths = numpy.array(
            [x.nonzero()[0].size for x in self.section_schedules])
 def num_priority1s(self, prog):
     return StudentRegistration.valid_objects().filter(
         relationship__name='Priority/1',
         section__parent_class__parent_program=prog).count()
 def enrollment_status(self, request, tl, one, two, module, extra, prog):
     resp = HttpResponse(content_type='application/json')
     data = StudentRegistration.valid_objects().filter(section__status__gt=0, section__parent_class__status__gt=0, section__parent_class__parent_program=prog, relationship__name='Enrolled').values_list('user__id', 'section__id')
     json.dump(list(data), resp)
     return resp
    def update_schedule_json(self, request, tl, one, two, module, extra, prog):
        resp = HttpResponse(content_type='application/json')
        result = {'user': None, 'sections': [], 'messages': []}
        try:
            user = ESPUser.objects.get(id=int(request.GET['user']))
        except:
            user = None
            result['messages'].append('Error: could find user %s' % request.GET.get('user', None))
        try:
            desired_sections = json.loads(request.GET['sections'])
        except:
            result['messages'].append('Error: could not parse requested sections %s' % request.GET.get('sections', None))
            desired_sections = None

        #   Check in student, since if they're using this view they must be onsite
        q = Record.objects.filter(user=user, program=prog, event='attended')
        if not q.exists():
            new_rec, created = Record.objects.get_or_create(user=user, program=prog, event='attended')

        if user and desired_sections is not None:
            override_full = (request.GET.get("override", "") == "true")

            current_sections = list(ClassSection.objects.filter(nest_Q(StudentRegistration.is_valid_qobject(), 'studentregistration'), status__gt=0, parent_class__status__gt=0, parent_class__parent_program=prog, studentregistration__relationship__name='Enrolled', studentregistration__user__id=user.id).values_list('id', flat=True).order_by('id').distinct())
            sections_to_remove = ClassSection.objects.filter(id__in=list(set(current_sections) - set(desired_sections)))
            sections_to_add = ClassSection.objects.filter(id__in=list(set(desired_sections) - set(current_sections)))

            failed_add_sections = []
            for sec in sections_to_add:
                if sec.isFull() and not override_full:
                    result['messages'].append('Failed to add %s (%s) to %s: %s (%s).  Error was: %s' % (user.name(), user.id, sec.emailcode(), sec.title(), sec.id, 'Class is currently full.'))
                    failed_add_sections.append(sec.id)

            if len(failed_add_sections) == 0:
                #   Remove sections the student wants out of
                for sec in sections_to_remove:
                    sec.unpreregister_student(user)
                    result['messages'].append('Removed %s (%s) from %s: %s (%s)' % (user.name(), user.id, sec.emailcode(), sec.title(), sec.id))

                #   Remove sections that conflict with those the student wants into
                sec_times = sections_to_add.select_related('meeting_times__id').values_list('id', 'meeting_times__id').order_by('meeting_times__id').distinct()
                sm = ScheduleMap(user, prog)
                existing_sections = []
                for (sec, ts) in sec_times:
                    if ts and ts in sm.map and len(sm.map[ts]) > 0:
                        #   We found something we need to remove
                        for sm_sec in sm.map[ts]:
                            if sm_sec.id not in sections_to_add:
                                sm_sec.unpreregister_student(user)
                                result['messages'].append('Removed %s (%s) from %s: %s (%s)' % (user.name(), user.id, sm_sec.emailcode(), sm_sec.title(), sm_sec.id))
                            else:
                                existing_sections.append(sm_sec)

                #   Add the sections the student wants
                for sec in sections_to_add:
                    if sec not in existing_sections and sec.id not in failed_add_sections:
                        error = sec.cannotAdd(user, not override_full)
                        if not error:
                            reg_result = sec.preregister_student(user, overridefull=override_full)
                            if not reg_result:
                                error = 'Class is currently full.'
                        else:
                            reg_result = False
                        if reg_result:
                            result['messages'].append('Added %s (%s) to %s: %s (%s)' % (user.name(), user.id, sec.emailcode(), sec.title(), sec.id))
                        else:
                            result['messages'].append('Failed to add %s (%s) to %s: %s (%s).  Error was: %s' % (user.name(), user.id, sec.emailcode(), sec.title(), sec.id, error))

            result['user'] = user.id
            result['sections'] = list(ClassSection.objects.filter(nest_Q(StudentRegistration.is_valid_qobject(), 'studentregistration'), status__gt=0, parent_class__status__gt=0, parent_class__parent_program=prog, studentregistration__relationship__name='Enrolled', studentregistration__user__id=result['user']).values_list('id', flat=True).distinct())

        json.dump(result, resp)
        return resp
Exemplo n.º 51
0
 def get_regdate(self, ordering='start_date'):
     regs = StudentRegistration.valid_objects().filter(user=self.user, section__parent_class__parent_program=self.program, relationship__name='Enrolled')
     if regs.exists():
         return regs.order_by(ordering).values_list('start_date', flat=True)[0].strftime("%Y-%m-%d %H:%M:%S")
 def students(self, QObject = False):
     q_sr = Q(studentregistration__section__parent_class__parent_program=self.program) & nest_Q(StudentRegistration.is_valid_qobject(), 'studentregistration')
     q_ssi = Q(studentsubjectinterest__subject__parent_program=self.program) & nest_Q(StudentSubjectInterest.is_valid_qobject(), 'studentsubjectinterest')
     if QObject:
         return {'twophase_star_students': q_ssi,
                 'twophase_priority_students' : q_sr}
     else:
         return {'twophase_star_students': ESPUser.objects.filter(q_ssi).distinct(),
                 'twophase_priority_students': ESPUser.objects.filter(q_sr).distinct()}
Exemplo n.º 53
0
# lunch randomly for users with both lunch blocks free.

from script_setup import *

import random

from esp.cal.models import Event
from esp.program.models import Program, StudentRegistration, RegistrationType
from esp.program.models.class_ import ClassSection
from esp.users.models import ESPUser

program = Program.objects.get(id=115)  # Change me! (Splash 2014)
relationship = RegistrationType.objects.get(name='Enrolled')

srs = StudentRegistration.valid_objects().filter(
    section__parent_class__parent_program=program,
    relationship=relationship)

srs_pairs = srs.values_list('user', 'section')

users = ESPUser.objects.filter(id__in=srs.values_list('user'))
sections = ClassSection.objects.filter(
    parent_class__parent_program=program
).prefetch_related('meeting_times')
timeblocks = Event.objects.filter(
    program=program, event_type__description='Class Time Block')

users_by_id = {user.id: user for user in users}
sections_by_id = {section.id: section for section in sections}
timeblocks_by_id = {timeblock.id: timeblock for timeblock in timeblocks}
sections_by_user_timeblock = {
 def isCompleted(self):
     return StudentRegistration.valid_objects().filter(user=get_current_request().user,
                                                       relationship__name="Request").exists()
    def studentreg2phase(self, request, tl, one, two, module, extra, prog):
        """
        Serves the two-phase student reg page. This page includes instructions
        for registration, and links to the phase1/phase2 sub-pages.
        """

        timeslot_dict = {}
        # Populate the timeslot dictionary with the priority to class title
        # mappings for each timeslot.
        priority_regs = StudentRegistration.valid_objects().filter(
            user=request.user, relationship__name__startswith='Priority')
        priority_regs = priority_regs.select_related(
            'relationship', 'section', 'section__parent_class')
        for student_reg in priority_regs:
            rel = student_reg.relationship
            title = student_reg.section.parent_class.title
            sec = student_reg.section
            times = sec.meeting_times.all().order_by('start')
            if times.count() == 0:
                continue
            timeslot = times[0].id
            if not timeslot in timeslot_dict:
                timeslot_dict[timeslot] = {rel: title}
            else:
                timeslot_dict[timeslot][rel] = title

        star_counts = {}
        interests = StudentSubjectInterest.valid_objects().filter(
            user=request.user, subject__parent_program=prog)
        interests = interests.select_related(
            'subject').prefetch_related('subject__sections__meeting_times')
        for interest in interests:
            cls = interest.subject
            for sec in cls.sections.all():
                times = sec.meeting_times.all()
                if len(times) == 0:
                    continue
                timeslot = min(times, key=lambda t: t.start).id
                if not timeslot in star_counts:
                    star_counts[timeslot] = 1
                else:
                    star_counts[timeslot] += 1

        # Iterate through timeslots and create a list of tuples of information
        prevTimeSlot = None
        blockCount = 0
        schedule = []
        timeslots = prog.getTimeSlots(types=['Class Time Block', 'Compulsory'])
        for i in range(len(timeslots)):
            timeslot = timeslots[i]
            if prevTimeSlot != None:
                if not Event.contiguous(prevTimeSlot, timeslot):
                    blockCount += 1

            if timeslot.id in timeslot_dict:
                priority_dict = timeslot_dict[timeslot.id]
                priority_list = sorted(priority_dict.items())
            else:
                priority_list = []
            if timeslot.id in star_counts:
                priority_list.append((
                    'Starred', "(%d classes)" % star_counts[timeslot.id]))
            schedule.append((timeslot, priority_list, blockCount + 1))

            prevTimeSlot = timeslot

        context = {}
        context['timeslots'] = schedule

        return render_to_response(
            self.baseDir()+'studentregtwophase.html', request, context)
from django.db.models.aggregates import Min

parser = argparse.ArgumentParser(description='Unenroll missing students from classes.')
parser.add_argument('program_id', type=int, help='ID of the current program')
parser.add_argument('--per-hour', dest='per_hour', action='store_true', help='Include this argument to clear registrations only for classes starting in the next 60 minutes.')

args = parser.parse_args()

enrolled = RegistrationType.objects.get(name='Enrolled')

prog = Program.objects.get(id=args.program_id)
relevant_sections = prog.sections().annotate(begin_time=Min("meeting_times__start")).filter(status=10, parent_class__status=10).exclude(parent_class__category__category='Lunch')
# classes that started more than 60 minutes ago
passed_sections = relevant_sections.filter(begin_time__lt=datetime.now() - timedelta(minutes=60))
# students who are enrolled in a class that started more than 60 minutes ago, who have not checked in
students = ESPUser.objects.filter(studentregistration__in=StudentRegistration.valid_objects(), studentregistration__relationship=enrolled, studentregistration__section__in=passed_sections).distinct().exclude(record__program=prog, record__event='attended')
# classes that start in the next 60 minutes
upcoming_sections = relevant_sections.filter(begin_time__gt=datetime.now())
if args.per_hour:
    upcoming_sections = upcoming_sections.filter(begin_time__lt=datetime.now() + timedelta(minutes=60))

# registrations of missing students for upcoming classes
registrations = StudentRegistration.valid_objects().filter(user__in=students, section__in=upcoming_sections, relationship=enrolled)
print "Candidate Registrations to Delete:", len(registrations)
print registrations
cmd_str = raw_input("Would you like to delete these registrations [y/N]? --> ")
if cmd_str.strip().lower() == 'y':
    registrations.update(end_date=datetime.now())
    print 'Expired:', registrations
else:
    print 'Action cancelled.'
 def isCompleted(self):
     return bool(StudentRegistration.valid_objects().filter(section__parent_class__parent_program=self.program, user=get_current_request().user))