Skip to content

Commit 8cc5ed7

Browse files
committed
Turn the class changes request form into a program module
I mostly just moved the code and didn't attempt serious cleanup. I did delete some things that are now handled by decorators, and fixed one bug introduced by not-quite-dead code removal last summer and one that's always been there which I accidentally found while testing.
1 parent f80269f commit 8cc5ed7

File tree

5 files changed

+137
-101
lines changed

5 files changed

+137
-101
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
__author__ = "Individual contributors (see AUTHORS file)"
2+
__date__ = "$DATE$"
3+
__rev__ = "$REV$"
4+
__license__ = "AGPL v.3"
5+
__copyright__ = """
6+
This file is part of the ESP Web Site
7+
Copyright (c) 2007 by the individual contributors
8+
(see AUTHORS file)
9+
10+
The ESP Web Site is free software; you can redistribute it and/or
11+
modify it under the terms of the GNU Affero General Public License
12+
as published by the Free Software Foundation; either version 3
13+
of the License, or (at your option) any later version.
14+
15+
This program is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
GNU Affero General Public License for more details.
19+
20+
You should have received a copy of the GNU Affero General Public
21+
License along with this program; if not, write to the Free Software
22+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23+
24+
Contact information:
25+
MIT Educational Studies Program
26+
84 Massachusetts Ave W20-467, Cambridge, MA 02139
27+
Phone: 617-253-4882
28+
29+
Learning Unlimited, Inc.
30+
527 Franklin St, Cambridge, MA 02139
31+
Phone: 617-379-0178
32+
33+
"""
34+
35+
from datetime import datetime
36+
from urllib import quote
37+
38+
from esp.program.models import Program, StudentAppResponse, StudentRegistration, RegistrationType
39+
from esp.program.models.class_ import ClassSubject
40+
from esp.program.modules.base import ProgramModuleObj
41+
from esp.program.modules.base import main_call, aux_call, needs_admin, needs_student, meets_grade
42+
from esp.web.util import render_to_response
43+
from esp.users.models.__init__ import ESPUser
44+
from esp.utils.query_utils import nest_Q
45+
46+
from django import forms
47+
from django.http import HttpResponseRedirect
48+
49+
50+
51+
class ClassChangeRequestModule(ProgramModuleObj):
52+
doc = """Let students enter a lottery to switch classes after the program has started."""
53+
54+
@classmethod
55+
def module_properties(cls):
56+
return {
57+
"admin_title": "Class Change Request",
58+
"link_title": "Class Change Request",
59+
"module_type": "learn",
60+
"required": False,
61+
}
62+
63+
class Meta:
64+
proxy = True
65+
66+
def is_completed(self):
67+
return True
68+
69+
def students(self, QObject=False):
70+
if QObject:
71+
return {}
72+
else:
73+
return {}
74+
75+
def studentDesc(self):
76+
return {}
77+
78+
@main_call
79+
@needs_student
80+
@meets_grade
81+
def classchangerequest(self, request, tl, one, two, module, extra, prog):
82+
timeslots = prog.getTimeSlots()
83+
sections = prog.sections().filter(status=10, meeting_times__isnull=False).distinct()
84+
85+
enrollments = {}
86+
for timeslot in timeslots:
87+
try:
88+
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)
89+
except ClassSubject.DoesNotExist:
90+
enrollments[timeslot] = None
91+
92+
context = {}
93+
context['timeslots'] = timeslots
94+
context['enrollments'] = enrollments
95+
context['user'] = request.user
96+
if 'success' in request.GET:
97+
context['success'] = True
98+
else:
99+
context['success'] = False
100+
101+
if request.user.isStudent():
102+
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])
103+
else:
104+
sections_by_slot = dict([(timeslot,[(section, False) for section in sections if section.get_meeting_times()[0] == timeslot]) for timeslot in timeslots])
105+
106+
fields = {}
107+
for i, timeslot in enumerate(sections_by_slot.keys()):
108+
choices = [('0', "I'm happy with my current enrollment.")]
109+
initial = '0'
110+
for section in sections_by_slot[timeslot]:
111+
choices.append((section[0].emailcode(), section[0].emailcode()+": "+section[0].title()))
112+
if section[1]:
113+
initial = section[0].emailcode()
114+
fields['timeslot_'+str(i+1)] = forms.ChoiceField(label="Timeslot "+str(i+1)+" ("+timeslot.pretty_time()+")", choices=choices, initial=initial)
115+
116+
form = type('ClassChangeRequestForm', (forms.Form,), fields)
117+
context['form'] = form()
118+
if request.method == "POST":
119+
old_requests = StudentRegistration.valid_objects().filter(user=context['user'], section__parent_class__parent_program=prog, relationship__name="Request")
120+
for r in old_requests:
121+
r.expire()
122+
form = form(request.POST)
123+
if form.is_valid():
124+
for value in form.cleaned_data.values():
125+
section = None
126+
for s in sections:
127+
if s.emailcode() == value:
128+
section = s
129+
break
130+
if not section:
131+
continue
132+
r = StudentRegistration.valid_objects().get_or_create(user=context['user'], section=section, relationship=RegistrationType.objects.get_or_create(name="Request", category="student")[0])[0]
133+
r.save()
134+
135+
return HttpResponseRedirect(request.path.rstrip('/')+'/?success')
136+
else:
137+
return render_to_response(self.baseDir() + 'classchangerequest.html', request, context)

esp/esp/urls.py

-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@
128128

129129

130130
# Program stuff
131-
(r'^(onsite|manage|teach|learn|volunteer)/([-A-Za-z0-9_ ]+)/([-A-Za-z0-9_ ]+)/classchangerequest/?$', 'classchangerequest'),
132131
(r'^(onsite|manage|teach|learn|volunteer|json)/([-A-Za-z0-9_ ]+)/([-A-Za-z0-9_ ]+)/([-A-Za-z0-9_ ]+)/([-A-Za-z0-9_ ]+)/?$', 'program'),
133132
(r'^(onsite|manage|teach|learn|volunteer|json)/([-A-Za-z0-9_ ]+)/([-A-Za-z0-9_ ]+)/([-A-Za-z0-9_ ]+)/?$', 'program'),
134133

esp/esp/users/models/__init__.py

-7
Original file line numberDiff line numberDiff line change
@@ -1047,13 +1047,6 @@ def getRankInClass(student, subject, default=10):
10471047
rank = default
10481048
return rank
10491049

1050-
@staticmethod
1051-
def getRankInSection(student, section, default=10):
1052-
if isinstance(section, int):
1053-
section = ClassSection.objects.get(id=section)
1054-
return getRankInClass(student, section.parent_class, default)
1055-
1056-
10571050
@dispatch.receiver(signals.pre_save, sender=ESPUser,
10581051
dispatch_uid='update_email_save')
10591052
def update_email_save(**kwargs):

esp/esp/web/views/main.py

-93
Original file line numberDiff line numberDiff line change
@@ -110,99 +110,6 @@ def program(request, tl, one, two, module, extra = None):
110110

111111
raise Http404
112112

113-
def classchangerequest(request, tl, one, two):
114-
from esp.program.models import Program, StudentAppResponse, StudentRegistration, RegistrationType
115-
from esp.program.models.class_ import ClassSubject
116-
from urllib import quote
117-
try:
118-
prog = Program.by_prog_inst(one, two)
119-
except Program.DoesNotExist:
120-
raise Http404("Program not found.")
121-
122-
if tl != "learn":
123-
raise Http404
124-
125-
if not request.user or not request.user.is_authenticated():
126-
return HttpResponseRedirect('%s?%s=%s' % (LOGIN_URL, REDIRECT_FIELD_NAME, quote(request.get_full_path()) ))
127-
128-
if not request.user.isStudent() and not request.user.isAdmin(prog):
129-
allowed_student_types = Tag.getTag("allowed_student_types", prog, default='')
130-
matching_user_types = any(x in request.user.groups.all().values_list("name",flat=True) for x in allowed_student_types.split(","))
131-
if not matching_user_types:
132-
return render_to_response('errors/program/notastudent.html', request, {})
133-
134-
errorpage = 'errors/program/wronggrade.html'
135-
136-
cur_grade = request.user.getGrade(prog)
137-
if (not Permission.user_has_perm(request.user, 'GradeOverride', program=prog) and (cur_grade != 0 and (cur_grade < prog.grade_min or cur_grade > prog.grade_max))):
138-
return render_to_response(errorpage, request, {'yog': request.user.getYOG(prog)})
139-
140-
setattr(request, "program", prog)
141-
setattr(request, "tl", tl)
142-
setattr(request, "module", "classchangerequest")
143-
144-
from django import forms
145-
from datetime import datetime
146-
from esp.utils.scheduling import getRankInClass
147-
148-
timeslots = prog.getTimeSlots()
149-
sections = prog.sections().filter(status=10, meeting_times__isnull=False).distinct()
150-
151-
enrollments = {}
152-
for timeslot in timeslots:
153-
try:
154-
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)
155-
except ClassSubject.DoesNotExist:
156-
enrollments[timeslot] = None
157-
158-
context = {}
159-
context['timeslots'] = timeslots
160-
context['enrollments'] = enrollments
161-
context['user'] = request.user
162-
if 'success' in request.GET:
163-
context['success'] = True
164-
else:
165-
context['success'] = False
166-
167-
if request.user.isStudent():
168-
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 getRankInClass(request.user, section) in (5,10)]) for timeslot in timeslots])
169-
else:
170-
sections_by_slot = dict([(timeslot,[(section, False) for section in sections if section.get_meeting_times()[0] == timeslot]) for timeslot in timeslots])
171-
172-
fields = {}
173-
for i, timeslot in enumerate(sections_by_slot.keys()):
174-
choices = [('0', "I'm happy with my current enrollment.")]
175-
initial = '0'
176-
for section in sections_by_slot[timeslot]:
177-
choices.append((section[0].emailcode(), section[0].emailcode()+": "+section[0].title()))
178-
if section[1]:
179-
initial = section[0].emailcode()
180-
fields['timeslot_'+str(i+1)] = forms.ChoiceField(label="Timeslot "+str(i+1)+" ("+timeslot.pretty_time()+")", choices=choices, initial=initial)
181-
182-
form = type('ClassChangeRequestForm', (forms.Form,), fields)
183-
context['form'] = form()
184-
if request.method == "POST":
185-
old_requests = StudentRegistration.valid_objects().filter(user=context['user'], section__parent_class__parent_program=prog, relationship__name="Request")
186-
for r in old_requests:
187-
r.expire()
188-
form = form(request.POST)
189-
if form.is_valid():
190-
for value in form.cleaned_data.values():
191-
section = None
192-
for s in sections:
193-
if s.emailcode() == value:
194-
section = s
195-
break
196-
if not section:
197-
continue
198-
r = StudentRegistration.objects.get_or_create(user=context['user'], section=section, relationship=RegistrationType.objects.get_or_create(name="Request", category="student")[0])[0]
199-
r.save()
200-
201-
return HttpResponseRedirect(request.path.rstrip('/')+'/?success')
202-
else:
203-
return render_to_response('program/classchangerequest.html', request, context)
204-
205-
206113
def archives(request, selection, category = None, options = None):
207114
""" Return a page with class archives """
208115

0 commit comments

Comments
 (0)