def prepare_program(program, data): """ This function adds custom stuff to save_instance to facilitate making programs happen. """ # Permissions format: perms = [] modules = [] perms += [('Student/All', None, data['student_reg_start'], data['student_reg_end'])] #it is recursive perms += [('Student/Catalog', None, data['student_reg_start'], None)] perms += [('Student/Profile', None, data['student_reg_start'], None)] perms += [('Teacher/All', None, data['teacher_reg_start'], data['teacher_reg_end'])] perms += [('Teacher/Classes/View', None, data['teacher_reg_start'], None)] perms += [('Teacher/MainPage', None, data['teacher_reg_start'], None)] perms += [('Teacher/Profile', None, data['teacher_reg_start'], None)] # Grant onsite bit (for all times) if an onsite user is available. if ESPUser.onsite_user(): perms += [('Onsite', ESPUser.onsite_user(), None, None)] modules += [(str(ProgramModule.objects.get(id=i)), i) for i in data['program_modules']] return perms, modules
def _value(self): user = ESPUser(self.user) node = self.node edit_verb = GetNode(EDIT_VERB_STRING) if not self.category: self.category = nav_category(node, section) if user: has_edit_bits = user.isAdministrator() else: has_edit_bits = False navbars = list(self.category.get_navbars().order_by('sort_rank')) navbar_context = [{ 'entry': x, 'has_bits': has_edit_bits } for x in navbars] # add program entries navbar_context = list( qsd_tree_program(navbar_context, node, section, user)) context = { 'node': node, 'has_edit_bits': has_edit_bits, 'qsdTree': navbar_context, 'section': section } return context
def paynow_cybersource(self, request, tl, one, two, module, extra, prog): if self.have_paid(): raise ESPError( False ), "You've already paid for this program; you can't pay again!" # Force users to pay for non-optional stuffs user = ESPUser(request.user) # Default line item types li_types = self.program.getLineItemTypes(user) invoice = Document.get_invoice(user, self.program_anchor_cached(parent=True), li_types, dont_duplicate=True) context = {} context['module'] = self context['one'] = one context['two'] = two context['tl'] = tl context['user'] = user context['itemizedcosts'] = invoice.get_items() try: context['itemizedcosttotal'] = invoice.cost() except EmptyTransactionException: context['itemizedcosttotal'] = 0 context['financial_aid'] = user.hasFinancialAid(prog.anchor) context['invoice'] = invoice return render_to_response(self.baseDir() + 'cardpay.html', request, (prog, tl), context)
def testGradeChange(self): # Create the admin user adminUser, c1 = ESPUser.objects.get_or_create(username='******') adminUser.set_password('password') adminUser.makeAdmin() # Create the student user studentUser, c2 = ESPUser.objects.get_or_create(username='******') # Make it a student studentUser.makeRole("Student") # Give it a starting grade student_studentinfo = StudentInfo(user=studentUser, graduation_year=ESPUser.YOGFromGrade(9)) student_studentinfo.save() student_regprofile = RegistrationProfile(user=studentUser, student_info=student_studentinfo, most_recent_profile=True) student_regprofile.save() # Check that the grade starts at 9 self.assertTrue(studentUser.getGrade() == 9) # Login the admin self.assertTrue(self.client.login(username="******", password="******")) testGrade = 11 curYear = ESPUser.current_schoolyear() gradYear = curYear + (12 - testGrade) self.client.get("/manage/userview?username=student&graduation_year="+str(gradYear)) self.assertTrue(studentUser.getGrade() == testGrade, "Grades don't match: %s %s" % (studentUser.getGrade(), testGrade)) # Clean up if (c1): adminUser.delete() if (c2): studentUser.delete()
def view_app(self, request, tl, one, two, module, extra, prog): scrmi = prog.getModuleExtension('StudentClassRegModuleInfo') reg_nodes = scrmi.reg_verbs() try: cls = ClassSubject.objects.get(id = extra) section = cls.default_section() except ClassSubject.DoesNotExist: raise ESPError(False), 'Cannot find class.' student = request.GET.get('student',None) if not student: student = request.POST.get('student','') try: student = ESPUser(User.objects.get(id = student)) except ESPUser.DoesNotExist: raise ESPError(False), 'Cannot find student, %s' % student if student.userbit_set.filter(qsc__parent=cls.anchor, verb__in=reg_nodes).count() == 0: raise ESPError(False), 'Student not a student of this class.' try: student.app = student.studentapplication_set.get(program = self.program) except: student.app = None assert False, student.studentapplication_set.all()[0].__dict__ raise ESPError(False), 'Error: Student did not apply. Student is automatically rejected.' return render_to_response(self.baseDir()+'app_popup.html', request, (prog, tl), {'class': cls, 'student': student})
def teacherhandout(self, request, tl, one, two, module, extra, prog, template_file='teacherschedules.html'): # Use the template defined in ProgramPrintables from esp.program.modules.handlers import ProgramPrintables context = {'module': self} pmos = ProgramModuleObj.objects.filter( program=prog, module__handler__icontains='printables') if pmos.count() == 1: pmo = ProgramPrintables(pmos[0]) teacher = ESPUser(request.user) scheditems = [] for cls in teacher.getTaughtClasses().filter( parent_program=self.program): if cls.isAccepted(): for section in cls.sections.all(): scheditems.append({ 'name': teacher.name(), 'teacher': teacher, 'cls': section }) scheditems.sort() context['scheditems'] = scheditems return render_to_response(pmo.baseDir() + template_file, request, context) else: raise ESPError( False ), 'No printables module resolved, so this document cannot be generated. Consult the webmasters.'
def testGradeChange(self): # Create the admin user adminUser, c1 = ESPUser.objects.get_or_create(username='******') adminUser.set_password('password') make_user_admin(adminUser) # Create the student user studentUser, c2 = ESPUser.objects.get_or_create(username='******') # Make it a student role_bit, created = UserBit.objects.get_or_create(user=studentUser, qsc=GetNode('Q'), verb=GetNode('V/Flags/UserRole/Student'), recursive=False) # Give it a starting grade student_studentinfo = StudentInfo(user=studentUser, graduation_year=ESPUser.YOGFromGrade(9)) student_studentinfo.save() student_regprofile = RegistrationProfile(user=studentUser, student_info=student_studentinfo, most_recent_profile=True) student_regprofile.save() # Check that the grade starts at 9 self.failUnless(studentUser.getGrade() == 9) # Login the admin self.failUnless(self.client.login(username="******", password="******")) testGrade = 11 curYear = ESPUser.current_schoolyear() gradYear = curYear + (12 - testGrade) self.client.get("/manage/userview?username=student&graduation_year="+str(gradYear)) self.failUnless(studentUser.getGrade() == testGrade, "Grades don't match: %s %s" % (studentUser.getGrade(), testGrade)) # Clean up if (c1): adminUser.delete() if (c2): studentUser.delete()
def rapidcheckin(self, request, tl, one, two, module, extra, prog): context = {} if request.method == 'POST': # Handle submission of student form = OnSiteRapidCheckinForm(request.POST) if form.is_valid(): student = ESPUser(form.cleaned_data['user']) # Check that this is a student user who is not also teaching (e.g. an admin) if student.isStudent() and student not in self.program.teachers()['class_approved']: recs = Record.objects.filter(user=student, event="attended", program=prog) if not recs.exists(): rec, created = Record.objects.get_or_create(user=student, event="attended", program=prog) context['message'] = '%s %s marked as attended.' % (student.first_name, student.last_name) if request.is_ajax(): return self.ajax_status(request, tl, one, two, module, extra, prog, context) else: context['message'] = '%s %s is not a student and has not been checked in' % (student.first_name, student.last_name) if request.is_ajax(): return self.ajax_status(request, tl, one, two, module, extra, prog, context) else: form = OnSiteRapidCheckinForm() context['module'] = self context['form'] = form return render_to_response(self.baseDir()+'ajaxcheckin.html', request, context)
def schoolyear(request): path_parts = request.path.lstrip('/').split('/') if len(path_parts) > 3: program_url = '/'.join(path_parts[1:3]) if Program.objects.filter(url=program_url).count() == 1: program = Program.objects.get(url=program_url) return {'schoolyear': ESPUser.program_schoolyear(program)} return {'schoolyear': ESPUser.current_schoolyear()}
def myesp_switchback(request, module): user = request.user user = ESPUser(user) user.updateOnsite(request) if not user.other_user: raise ESPError(False), 'You were not another user!' return HttpResponseRedirect(user.switch_back(request))
def survey_review_single(request, tl, program, instance): """ View a single survey response. """ try: prog = Program.by_prog_inst(program, instance) except Program.DoesNotExist: #raise Http404 raise ESPError(), "Can't find the program %s/%s" % (program, instance) user = ESPUser(request.user) survey_response = None ints = request.REQUEST.items() if len(ints) == 1: srs = SurveyResponse.objects.filter(id=ints[0][0]) if len(srs) == 1: survey_response = srs[0] if survey_response is None: raise ESPError( False ), 'Ideally this page should give you some way to pick an individual response. For now I guess you should go back to <a href="review">reviewing the whole survey</a>.' if tl == 'manage' and user.isAdmin(prog): answers = survey_response.answers.order_by('content_type', 'object_id', 'question') classes_only = False other_responses = None elif tl == 'teach': subject_ct = ContentType.objects.get(app_label="program", model="classsubject") section_ct = ContentType.objects.get(app_label="program", model="classsection") class_ids = [x["id"] for x in user.getTaughtClasses().values('id')] section_ids = [x["id"] for x in user.getTaughtSections().values('id')] answers = survey_response.answers.filter( content_type__in=[subject_ct, section_ct], object_id__in=(class_ids + section_ids)).order_by( 'content_type', 'object_id', 'question') classes_only = True other_responses = SurveyResponse.objects.filter( answers__content_type=subject_ct, answers__object_id__in=class_ids).order_by('id').distinct() else: raise ESPError( False ), 'You need to be a teacher or administrator of this program to review survey responses.' context = { 'user': user, 'program': prog, 'response': survey_response, 'answers': answers, 'classes_only': classes_only, 'other_responses': other_responses } return render_to_response('survey/review_single.html', request, context)
def prepare_context(self, program, target_path=None): context = {} context['program'] = program context['user_types'] = ESPUser.getTypes() category_lists = {} list_descriptions = program.getListDescriptions() # Add in program-specific lists for most common user types for user_type, list_func in zip(Program.USER_TYPES_WITH_LIST_FUNCS, Program.USER_TYPE_LIST_FUNCS): raw_lists = getattr(program, list_func)(True) category_lists[user_type] = [{ 'name': key, 'list': raw_lists[key], 'description': list_descriptions[key] } for key in raw_lists] for item in category_lists[user_type]: if item['name'] in UserSearchController.preferred_lists: item['preferred'] = True # Add in global lists for each user type for user_type in ESPUser.getTypes(): key = user_type.lower() + 's' if user_type not in category_lists: category_lists[user_type] = [] category_lists[user_type].insert( 0, { 'name': 'all_%s' % user_type, 'list': ESPUser.getAllOfType(user_type), 'description': 'All %s in the database' % key, 'preferred': True, 'all_flag': True }) # Add in mailing list accounts category_lists['emaillist'] = [{ 'name': 'all_emaillist', 'list': Q(password='******'), 'description': 'Everyone signed up for the mailing list', 'preferred': True }] context['lists'] = category_lists context['all_list_names'] = [] for category in category_lists: for item in category_lists[category]: context['all_list_names'].append(item['name']) if target_path is None: target_path = '/manage/%s/commpanel' % program.getUrlBase() context['action_path'] = target_path context['groups'] = Group.objects.all() return context
def user_registration_validate(request): """Handle the account creation logic when the form is submitted This function is overloaded to handle either one or two phase reg""" if not Tag.getBooleanTag("ask_about_duplicate_accounts",default=False): form = SinglePhaseUserRegForm(request.POST) else: form = UserRegForm(request.POST) if form.is_valid(): try: #there is an email-only account with that email address to upgrade user = ESPUser.objects.get(email=form.cleaned_data['email'], password = '******') except ESPUser.DoesNotExist: try: #there is an inactive account with that username user = ESPUser.objects.filter( username = form.cleaned_data['username'], is_active = False).latest('date_joined') except ESPUser.DoesNotExist: user = ESPUser(email = form.cleaned_data['email']) user.username = form.cleaned_data['username'] user.last_name = form.cleaned_data['last_name'] user.first_name = form.cleaned_data['first_name'] user.set_password(form.cleaned_data['password']) # Append key to password and disable until activation if desired if Tag.getBooleanTag('require_email_validation', default=False): userkey = random.randint(0,2**31 - 1) user.password += "_%d" % userkey user.is_active = False user.save() ESPUser_Profile.objects.get_or_create(user = user) user.groups.add(Group.objects.get(name=form.cleaned_data['initial_role'])) if not Tag.getBooleanTag('require_email_validation', default=False): user = authenticate(username=form.cleaned_data['username'], password=form.cleaned_data['password']) login(request, user) return HttpResponseRedirect('/myesp/profile/') else: send_activation_email(user,userkey) return render_to_response('registration/account_created_activation_required.html', request, {'user': user, 'site': Site.objects.get_current()}) else: return render_to_response('registration/newuser.html', request, {'form':form})
def preview_miniblog(request, section=None): """this function will return the last n miniblog entries from preview_miniblog """ # last update: Axiak if request.user != None: curUser = ESPUser(request.user) else: curUser = ESPUser(AnonymousUser()) return curUser.getMiniBlogEntries()
def prepare_program(program, data): """ This function adds custom stuff to save_instance to facilitate making programs happen. """ # Datatrees format: each item is a tuple of (node URI, friendly name) datatrees = [] # Userbits format: each item is a tuple of (QSC URI, user ID, startdate, enddate) userbits = [] modules = [] # Fetch/create the program node program_node_name = program.anchor.get_uri() + '/' + data['term'] # Create the DataTree branches for sub_node in ProgramTemplate: datatrees += [(program_node_name + sub_node, '')] userbits += [('V/Flags/Public', None, data['publish_start'], data['publish_end'])] userbits += [('V/Deadline/Registration/Student', None, data['student_reg_start'], data['student_reg_end'])] #userbits += [('V/Deadline/Registration/Student/Applications', None, data['student_reg_start'], data['student_reg_end'])] userbits += [('V/Deadline/Registration/Student/Catalog', None, data['student_reg_start'], None)] #userbits += [('V/Deadline/Registration/Student/Classes', None, data['student_reg_start'], data['student_reg_end'])] #userbits += [('V/Deadline/Registration/Student/Classes/OneClass', None, data['student_reg_start'], data['student_reg_end'])] #userbits += [('V/Deadline/Registration/Student/Confirm', None, data['student_reg_start'], data['publish_end'])] #userbits += [('V/Deadline/Registration/Student/ExtraCosts', None, data['student_reg_start'], data['student_reg_end'])] #userbits += [('V/Deadline/Registration/Student/MainPage', None, data['student_reg_start'], data['publish_end'])] #userbits += [('V/Deadline/Registration/Student/Payment', None, data['student_reg_start'], data['publish_end'])] userbits += [('V/Deadline/Registration/Teacher', None, data['teacher_reg_start'], data['teacher_reg_end'])] #userbits += [('V/Deadline/Registration/Teacher/Catalog', None, data['teacher_reg_start'], None)] #userbits += [('V/Deadline/Registration/Teacher/Classes', None, data['teacher_reg_start'], data['teacher_reg_end'])] userbits += [('V/Deadline/Registration/Teacher/Classes/View', None, data['teacher_reg_start'], None)] userbits += [('V/Deadline/Registration/Teacher/MainPage', None, data['teacher_reg_start'], None)] userbits += [('V/Deadline/Registration/Teacher/Profile', None, data['teacher_reg_start'], None)] # Grant onsite bit (for all times) if an onsite user is available. if ESPUser.onsite_user(): userbits += [('V/Registration/OnSite', ESPUser.onsite_user(), None, None)] for director in data['admins']: userbits += [('V/Administer', ESPUser.objects.get(id=int(director)), None, None)] json_module = ProgramModule.objects.get(handler=u'JSONDataModule') # get the JSON Data Module # If the JSON Data Module isn't already in the list of selected # program modules, add it. The JSON Data Module is a dependency for # many commonly-used modules, so it is important that it be enbabled # by default for all new programs. if json_module.id not in data['program_modules']: data['program_modules'].append(json_module.id) modules += [(str(ProgramModule.objects.get(id=i)), i) for i in data['program_modules']] return datatrees, userbits, modules
def _checkAdmin(moduleObj, request, *args, **kwargs): if not_logged_in(request): return HttpResponseRedirect('%s?%s=%s' % (LOGIN_URL, REDIRECT_FIELD_NAME, quote(request.get_full_path()))) if not request.user.isOnsite(moduleObj.program) and not request.user.isAdmin(moduleObj.program): user = request.user user = ESPUser(user) user.updateOnsite(request) ouser = user.get_old(request) if not user.other_user or (not ouser.isOnsite(moduleObj.program) and not ouser.isAdmin(moduleObj.program)): return render_to_response('errors/program/notonsite.html', request, (moduleObj.program, 'onsite'), {}) return method(moduleObj, request, *args, **kwargs)
def login_checked(request, *args, **kwargs): if request.user.is_authenticated(): # Set response cookies in case of repeat login reply = HttpMetaRedirect('/') reply._new_user = request.user reply.no_set_cookies = False return reply reply = login(request, *args, **kwargs) # Check for user forwarders if request.user.is_authenticated(): old_username = request.user.username user, forwarded = UserForwarder.follow(ESPUser(request.user)) if forwarded: auth_logout(request) auth_login(request, user) # Try to display a friendly error message next_uri = reply.get('Location', '').strip() if next_uri: context = { 'request': request, 'old_username': old_username, 'next_uri': next_uri, 'next_title': next_uri, } if next_uri == '/': context['next_title'] = 'the home page' return render_to_response('users/login_duplicate_warning.html', request, request.get_node('Q/Web/myesp'), context) mask_locations = ['/', '/myesp/signout/', '/admin/logout/'] if reply.get('Location', '') in mask_locations: # We're getting redirected to somewhere undesirable. # Let's try to do something smarter. request.user = ESPUser(request.user) if request.user.isTeacher(): reply = HttpMetaRedirect("/teach/index.html") else: reply = HttpMetaRedirect("/learn/index.html") elif reply.status_code == 302: # Even if the redirect was going to a reasonable place, we need to # turn it into a 200 META redirect in order to set the cookies properly. request.user = ESPUser(request.user) reply = HttpMetaRedirect(reply.get('Location', '')) # Stick the user in the response in order to set cookies if necessary reply._new_user = request.user reply.no_set_cookies = False return reply
def process(self, processoverride=False): """ Process this request...if it's an email, create all the necessary email requests. """ # if we already processed, return if self.processed and not processoverride: return # there's no real thing for this...yet if not self.email_all: return # this is for thread-safeness... self.processed = True self.save() # figure out who we're sending from... if self.sender is not None and len(self.sender.strip()) > 0: send_from = self.sender else: if self.creator is not None: send_from = '%s <%s>' % (ESPUser( self.creator).name(), self.creator.email) else: send_from = 'ESP Web Site <*****@*****.**>' users = self.recipients.getList(ESPUser) try: users = users.distinct() except: pass # go through each user and parse the text...then create the proper # emailrequest and textofemail object for user in users: user = ESPUser(user) newemailrequest = EmailRequest(target=user, msgreq=self) newtxt = TextOfEmail( send_to='%s <%s>' % (user.name(), user.email), send_from=send_from, subject=self.parseSmartText(self.subject, user), msgtext=self.parseSmartText(self.msgtext, user), sent=None) newtxt.save() newemailrequest.textofemail = newtxt newemailrequest.save() print 'Prepared e-mails to send for message request %d: %s' % ( self.id, self.subject)
def viewResponse(request, form_id): """ Viewing response data """ if request.user.is_authenticated and (ESPUser(request.user).isTeacher() or ESPUser( request.user).isAdministrator()): try: form_id = int(form_id) except ValueError: raise Http404 form = Form.objects.get(id=form_id) return render_to_response('customforms/view_results.html', {'form': form}) else: return HttpResponseRedirect('/')
def printschedules(self, request, tl, one, two, module, extra, prog): " A link to print a schedule. " if not request.GET.has_key('sure') and not request.GET.has_key('gen_img'): printers = Printer.objects.all().values_list('name', flat=True) return render_to_response(self.baseDir()+'instructions.html', request, {'printers': printers}) if request.GET.has_key('sure'): return render_to_response(self.baseDir()+'studentschedulesrenderer.html', request, {}) requests = PrintRequest.objects.filter(time_executed__isnull=True) if extra and Printer.objects.filter(name=extra).exists(): requests = requests.filter(printer__name=extra) for req in requests: req.time_executed = datetime.now() req.save() # get students old_students = set([ ESPUser(req.user) for req in requests ]) if len(old_students) > 0: response = ProgramPrintables.get_student_schedules(request, list(old_students), prog, onsite=True) # set the refresh rate #response['Refresh'] = '2' return response else: # No response if no users return HttpResponse('')
def process(self, user, user_match): try: user = ESPUser.objects.get(username__iexact = user) except ESPUser.DoesNotExist: return user = ESPUser(user) # DIRTY HACK to allow mailing aliases to still work for local Mailman messages if user.isTeacher() or self.message['List-Id']: del(self.message['to']) self.message['to'] = user.email self.direct_send = True self.send = True return
def userview(request): """ Render a template displaying all the information about the specified user """ try: user = ESPUser.objects.get(username=request.GET['username']) except: raise ESPError(False), "Sorry, can't find anyone with that username." teacherbio = TeacherBio.getLastBio(user) if not teacherbio.picture: teacherbio.picture = 'images/not-available.jpg' from esp.users.forms.user_profile import StudentInfoForm if 'graduation_year' in request.GET: student_info = user.getLastProfile().student_info student_info.graduation_year = int(request.GET['graduation_year']) student_info.save() change_grade_form = StudentInfoForm(user=user) if 'disabled' in change_grade_form.fields['graduation_year'].widget.attrs: del change_grade_form.fields['graduation_year'].widget.attrs['disabled'] change_grade_form.fields['graduation_year'].initial = ESPUser.YOGFromGrade(user.getGrade()) change_grade_form.fields['graduation_year'].choices = filter(lambda choice: bool(choice[0]), change_grade_form.fields['graduation_year'].choices) context = { 'user': user, 'taught_classes' : user.getTaughtClasses().order_by('parent_program', 'id'), 'enrolled_classes' : user.getEnrolledSections().order_by('parent_class__parent_program', 'id'), 'taken_classes' : user.getSections().order_by('parent_class__parent_program', 'id'), 'teacherbio': teacherbio, 'domain': settings.SITE_INFO[1], 'change_grade_form': change_grade_form, } return render_to_response("users/userview.html", request, context )
def gen_perm(tup): new_perm = Permission(permission_type=tup[0], program=prog) if tup[2]: new_perm.start_date = tup[2] if tup[3]: new_perm.end_date = tup[3] if tup[1] is not None: new_perm.user = tup[1] new_perm.save() return elif tup[1] is None and tup[0].startswith("Student"): new_perm.role = Group.objects.get(name="Student") new_perm.save() return elif tup[1] is None and tup[0].startswith("Teacher"): new_perm.role = Group.objects.get(name="Teacher") new_perm.save() return #It's not for a specific user and not a teacher or student deadline for x in ESPUser.getTypes(): newnew_perm = Permission(permission_type=new_perm.permission_type, role=Group.objects.get(name=x), start_date=new_perm.start_date, end_date=new_perm.end_date, program=prog) newnew_perm.save()
def hasPerm(user, form): """ Checks if this user qualifies to view this form """ if (not form.anonymous or form.perms != "") and not user.is_authenticated(): return False, "You need to be logged in to view this form." if form.perms == "": return True, "" else: perms_list = form.perms.strip(',').split(',') main_perm = perms_list[0] prog_id = "" sub_perms = None if len(perms_list) > 1: prog_id = perms_list[1] if len(perms_list) > 2: sub_perms = perms_list[2:] Qlist = [] Qlist.append(ESPUser.getAllOfType( main_perm)) # Check -> what to do with students? if sub_perms: if prog_id != "": prog = Program.objects.get(pk=int(prog_id)) all_Qs = prog.getLists(QObjects=True) for perm in sub_perms: Qlist.append(all_Qs[perm]['list']) if ESPUser.objects.filter(id=user.id).filter(*Qlist).exists(): return True, "" else: return False, "You are not permitted to view this form."
def students_status(self, request, tl, one, two, module, extra, prog): resp = HttpResponse(mimetype='application/json') grade_query = """ SELECT (12 + %d - "users_studentinfo"."graduation_year") FROM "users_studentinfo", "program_registrationprofile" WHERE "program_registrationprofile"."most_recent_profile" = true AND "program_registrationprofile"."student_info_id" = "users_studentinfo"."id" AND "users_studentinfo"."user_id" = "auth_user"."id" ORDER BY program_registrationprofile.id DESC LIMIT 1 """ % ESPUser.current_schoolyear() # Try to ensure we don't miss anyone students_dict = self.program.students(QObjects=True) student_types = [ 'student_profile' ] # You could add more list names here, but it would get very slow. students_Q = Q() for student_type in student_types: students_Q = students_Q | students_dict[student_type] students = ESPUser.objects.filter(students_Q).distinct() data = students.extra({ 'grade': grade_query }).values_list('id', 'last_name', 'first_name', 'grade').distinct() simplejson.dump(list(data), resp) return resp
def __init__(self, *args, **kwargs): # Set up the default form super(UserRegForm, self).__init__(*args, **kwargs) # Adjust initial_role choices role_choices = [(item[0], item[1]['label']) for item in ESPUser.getAllUserTypes()] self.fields['initial_role'].choices = [('', 'Pick one...')] + role_choices
def testMorph(self): class scratchCls(object): pass class scratchDict(dict): def cycle_key(self): pass def flush(self): for i in self.keys(): del self[i] # Make up a fake request object # This definitely doesn't meet the spec of the real request object; # if tests fail as a result in the future, it'll need to be fixed. request = scratchCls() request.backend = 'django.contrib.auth.backends.ModelBackend' request.user = None request.session = scratchDict() # Create a couple users and a userbit self.user, created = ESPUser.objects.get_or_create( username='******') self.userbit = UserBit.objects.get_or_create( user=self.user, verb=GetNode('V/Administer'), qsc=GetNode('Q')) self.basic_user, created = ESPUser.objects.get_or_create( username='******') self.userbit = UserBit.objects.get_or_create( user=self.basic_user, verb=GetNode('V/Flags/UserRole/Student'), qsc=GetNode('Q')) self.user.backend = request.backend self.basic_user.backend = request.backend login(request, self.user) self.assertEqual(request.user, self.user, "Failed to log in as '%s'" % self.user) request.user.switch_to_user(request, self.basic_user, None, None) self.assertEqual(request.user, self.basic_user, "Failed to morph into '%s'" % self.basic_user) request.user.switch_back(request) self.assertEqual(request.user, self.user, "Failed to morph back into '%s'" % self.user) blocked_illegal_morph = True try: ESPUser(request.user).switch_to_user(request, self.basic_user, None, None) self.assertEqual(request.user, self.basic_user, "Failed to morph into '%s'" % self.basic_user) except ESPError(): blocked_illegal_morph = True self.assertTrue(blocked_illegal_morph, "User '%s' was allowed to morph into an admin!")
def gen_perm(tup): new_perm=Permission(permission_type=tup[0], program=prog) if tup[2]: new_perm.start_date = tup[2] if tup[3]: new_perm.end_date = tup[3] if tup[1] is not None: new_perm.user=tup[1] new_perm.save() return elif tup[1] is None and tup[0].startswith("Student"): new_perm.role=Group.objects.get(name="Student") new_perm.save() return elif tup[1] is None and tup[0].startswith("Teacher"): new_perm.role=Group.objects.get(name="Teacher") new_perm.save() return #It's not for a specific user and not a teacher or student deadline for x in ESPUser.getTypes(): newnew_perm=Permission(permission_type=new_perm.permission_type, role=Group.objects.get(name=x), start_date=new_perm.start_date, end_date=new_perm.end_date, program=prog) newnew_perm.save()
def payonline(self, request, tl, one, two, module, extra, prog): user = ESPUser(request.user) iac = IndividualAccountingController(self.program, request.user) context = {} context['module'] = self context['one'] = one context['two'] = two context['tl'] = tl context['user'] = user context['invoice_id'] = iac.get_id() context['identifier'] = iac.get_identifier() payment_type = iac.default_payments_lineitemtype() sibling_type = iac.default_siblingdiscount_lineitemtype() grant_type = iac.default_finaid_lineitemtype() context['itemizedcosts'] = iac.get_transfers().exclude( line_item__in=[payment_type, sibling_type, grant_type]).order_by( '-line_item__required') context['itemizedcosttotal'] = iac.amount_due() context['subtotal'] = iac.amount_requested() context['financial_aid'] = iac.amount_finaid() context['sibling_discount'] = iac.amount_siblingdiscount() context['amount_paid'] = iac.amount_paid() if 'HTTP_HOST' in request.META: context['hostname'] = request.META['HTTP_HOST'] else: context['hostname'] = Site.objects.get_current().domain context['institution'] = settings.INSTITUTION_NAME context['storename'] = self.store_id context['support_email'] = settings.DEFAULT_EMAIL_ADDRESSES['support'] return render_to_response(self.baseDir() + 'cardpay.html', request, context)
def paynow_cybersource(self, request, tl, one, two, module, extra, prog): # Force users to pay for non-optional stuffs user = ESPUser(request.user) iac = IndividualAccountingController(self.program, request.user) context = {} context['module'] = self context['one'] = one context['two'] = two context['tl'] = tl context['user'] = user context['invoice_id'] = iac.get_id() context['identifier'] = iac.get_identifier() payment_type = iac.default_payments_lineitemtype() sibling_type = iac.default_siblingdiscount_lineitemtype() grant_type = iac.default_finaid_lineitemtype() context['itemizedcosts'] = iac.get_transfers().exclude( line_item__in=[payment_type, sibling_type, grant_type]).order_by( '-line_item__required') context['itemizedcosttotal'] = iac.amount_due() context['subtotal'] = iac.amount_requested() context['financial_aid'] = iac.amount_finaid() context['sibling_discount'] = iac.amount_siblingdiscount() context['amount_paid'] = iac.amount_paid() return render_to_response(self.baseDir() + 'cardpay.html', request, context)
def hasPerm(user, form): """ Checks if this user qualifies to view this form """ if (not form.anonymous or form.perms!="") and not user.is_authenticated(): return False, "You need to be logged in to view this form." if form.perms == "": return True, "" else: perms_list = form.perms.strip(',').split(',') main_perm = perms_list[0] prog_id = "" sub_perms = None if len(perms_list)>1: prog_id = perms_list[1] if len(perms_list)>2: sub_perms = perms_list[2:] Qlist = [] Qlist.append(ESPUser.getAllOfType(main_perm)) # Check -> what to do with students? if sub_perms: if prog_id != "": prog = Program.objects.get(pk=int(prog_id)) all_Qs = prog.getLists(QObjects=True) for perm in sub_perms: Qlist.append(all_Qs[perm]['list']) if ESPUser.objects.filter(id=user.id).filter(*Qlist).exists(): return True, "" else: return False, "You are not permitted to view this form."
def idebug_hook(request, context): if not hasattr(request, 'idebug') or not request.idebug: return # Exit quickly if we're not logged in and no GET flag was given logged_in = hasattr(request, 'user') and hasattr( request, 'session') and request.user.is_authenticated() has_idebug = 'idebug' in request.GET if not logged_in and not has_idebug: return is_admin = logged_in and ESPUser(request.user).isAdministrator() idebug_pw = request.GET['idebug'] if has_idebug else '' show = False if 'idebug' in request.session: show = request.session['idebug'] if is_admin and has_idebug and idebug_pw == '': show = True if is_admin and has_idebug and (idebug_pw in ('1', 'on', 'yes', 'True')): show = True request.session['idebug'] = True if idebug_pw in ('0', 'off', 'no', 'False'): show = False request.session['idebug'] = False if hasattr(settings, 'IDEBUG_PASSWORD') and len(settings.IDEBUG_PASSWORD) > 4: if idebug_pw == settings.IDEBUG_PASSWORD: show = True if not show: return idebug_data = list() # Add the query info first, so we don't capture queries performed during context dump for q in connection.queries: idebug_data.append(('QUERY', '(%ss) %s' % (q['time'], q['sql']))) # Add in cache info if hasattr(cache, 'queries'): for q in cache.queries: idebug_data.append( ('CACHE', '%s(\'%s\') = \'%s\'' % (q['method'], q['key'], q['value']))) # Loop through the context and dump the contents intelligently for subdict in context: for k, v in subdict.iteritems(): idebug_data.append((k, debug_print(k, v))) context['idebug'] = idebug_data return
def save(self): # Reset user's offers if self.cleaned_data['user']: user = ESPUser.objects.get(id=self.cleaned_data['user']) user.volunteeroffer_set.all().delete() if self.cleaned_data.get('clear_requests', False): # They want to cancel all shifts - don't do anything further. return [] # Create user if one doesn't already exist, otherwise associate a user. # Note that this will create a new user account if they enter an e-mail # address different from the one on file. if not self.cleaned_data['user']: user_data = { 'first_name': self.cleaned_data['name'].split()[0], 'last_name': ' '.join(self.cleaned_data['name'].split()[1:]), 'email': self.cleaned_data['email'], } existing_users = ESPUser.objects.filter( **user_data).order_by('-id') if existing_users.exists(): # Arbitrarily pick the most recent account # This is not too important, we just need a link to an e-mail address. user = existing_users[0] else: auto_username = ESPUser.get_unused_username( user_data['first_name'], user_data['last_name']) user = ESPUser.objects.create_user(auto_username, user_data['email']) user.__dict__.update(user_data) user.save() # Record this user account as a volunteer user.makeVolunteer() # Remove offers with the same exact contact info VolunteerOffer.objects.filter(email=self.cleaned_data['email'], phone=self.cleaned_data['phone'], name=self.cleaned_data['name']).delete() offer_list = [] for req in self.cleaned_data['requests']: o = VolunteerOffer() o.user_id = user.id o.email = self.cleaned_data['email'] o.phone = self.cleaned_data['phone'] o.name = self.cleaned_data['name'] o.confirmed = self.cleaned_data['confirm'] if 'shirt_size' in self.cleaned_data: o.shirt_size = self.cleaned_data['shirt_size'] if 'shirt_type' in self.cleaned_data: o.shirt_type = self.cleaned_data['shirt_type'] if 'comments' in self.cleaned_data: o.comments = self.cleaned_data['comments'] o.request_id = req o.save() offer_list.append(o) return offer_list
def studentDesc(self): # Label these heading nicely like the user registration form role_choices = ESPUser.getAllUserTypes() role_dict = {} for item in role_choices: role_dict[item[0]] = item[1] return {'classreg': """Students who signed up for at least one class""", 'enrolled': """Students who are enrolled in at least one class"""}
def save(self): # Reset user's offers if self.cleaned_data['user']: user = ESPUser.objects.get(id=self.cleaned_data['user']) user.volunteeroffer_set.all().delete() if self.cleaned_data.get('clear_requests', False): # They want to cancel all shifts - don't do anything further. return [] # Create user if one doesn't already exist, otherwise associate a user. # Note that this will create a new user account if they enter an e-mail # address different from the one on file. if not self.cleaned_data['user']: user_data = {'first_name': self.cleaned_data['name'].split()[0], 'last_name': ' '.join(self.cleaned_data['name'].split()[1:]), 'email': self.cleaned_data['email'], } existing_users = ESPUser.objects.filter(**user_data).order_by('-id') if existing_users.exists(): # Arbitrarily pick the most recent account # This is not too important, we just need a link to an e-mail address. user = existing_users[0] else: auto_username = ESPUser.get_unused_username(user_data['first_name'], user_data['last_name']) user = ESPUser.objects.create_user(auto_username, user_data['email']) user.__dict__.update(user_data) user.save() # Record this user account as a volunteer user.makeVolunteer() # Remove offers with the same exact contact info VolunteerOffer.objects.filter(email=self.cleaned_data['email'], phone=self.cleaned_data['phone'], name=self.cleaned_data['name']).delete() offer_list = [] for req in self.cleaned_data['requests']: o = VolunteerOffer() o.user_id = user.id o.email = self.cleaned_data['email'] o.phone = self.cleaned_data['phone'] o.name = self.cleaned_data['name'] o.confirmed = self.cleaned_data['confirm'] if 'shirt_size' in self.cleaned_data: o.shirt_size = self.cleaned_data['shirt_size'] if 'shirt_type' in self.cleaned_data: o.shirt_type = self.cleaned_data['shirt_type'] if 'comments' in self.cleaned_data: o.comments = self.cleaned_data['comments'] o.request_id = req o.save() offer_list.append(o) return offer_list
def bio(request, tl, last = '', first = '', usernum = 0, username = ''): """ Displays a teacher bio """ try: if username != '': founduser = ESPUser.objects.get(username=username) old_url = (tl != 'teach') else: founduser = ESPUser.getUserFromNum(first, last, usernum) old_url = True except: return bio_not_found(request) return bio_user(request, founduser, old_url)
def prepare_context(self, program, target_path=None): context = {} context['program'] = program context['user_types'] = ESPUser.getTypes() category_lists = {} list_descriptions = program.getListDescriptions() # Add in program-specific lists for most common user types for user_type, list_func in zip(Program.USER_TYPES_WITH_LIST_FUNCS, Program.USER_TYPE_LIST_FUNCS): raw_lists = getattr(program, list_func)(True) category_lists[user_type] = [{'name': key, 'list': raw_lists[key], 'description': list_descriptions[key]} for key in raw_lists] for item in category_lists[user_type]: if item['name'] in UserSearchController.preferred_lists: item['preferred'] = True # Add in global lists for each user type for user_type in ESPUser.getTypes(): key = user_type.lower() + 's' if user_type not in category_lists: category_lists[user_type] = [] category_lists[user_type].insert(0, {'name': 'all_%s' % user_type, 'list': ESPUser.getAllOfType(user_type), 'description': 'All %s in the database' % key, 'preferred': True, 'all_flag': True}) # Add in mailing list accounts category_lists['emaillist'] = [{'name': 'all_emaillist', 'list': Q(password = '******'), 'description': 'Everyone signed up for the mailing list', 'preferred': True}] context['lists'] = category_lists context['all_list_names'] = [] for category in category_lists: for item in category_lists[category]: context['all_list_names'].append(item['name']) if target_path is None: target_path = '/manage/%s/commpanel' % program.getUrlBase() context['action_path'] = target_path return context
def schedule_students(self, request, tl, one, two, module, extra, prog): """ Redirect to student registration, having morphed into the desired student. """ user, found = search_for_user(request, ESPUser.getAllOfType('Student', False)) if not found: return user request.user.switch_to_user(request, user, self.getCoreURL(tl), 'OnSite Registration!', True) return HttpResponseRedirect('/learn/%s/studentreg' % self.program.getUrlBase())
def bio_edit(request, tl='', last='', first='', usernum=0, progid = None, username=''): """ Edits a teacher bio, given user and program identification information """ old_url = False try: if tl == '': founduser = request.user else: if username != '': founduser = ESPUser.objects.get(username=username) old_url = (tl != 'teach') else: founduser = ESPUser.getUserFromNum(first, last, usernum) old_url = True except: return bio_not_found(request) foundprogram = get_from_id(progid, Program, 'program', False) return bio_edit_user_program(request, founduser, foundprogram, old_url=old_url)
def query_from_criteria(self, user_type, criteria): """ Get the "base list" consisting of all the users of a specific type. """ if user_type.lower() == 'any': Q_base = Q() else: if user_type not in ESPUser.getTypes(): raise ESPError('user_type must be one of '+str(ESPUser.getTypes())) Q_base = ESPUser.getAllOfType(user_type, True) Q_include = Q() Q_exclude = Q() """ Apply the specified criteria to filter the list of users. """ if criteria.get('userid', '').strip(): ## Select users based on their IDs only userid = [] for digit in criteria['userid'].split(','): try: userid.append(int(digit)) except: raise ESPError('User id invalid, please enter a number or comma-separated list of numbers.', log=False) if 'userid__not' in criteria: Q_exclude &= Q(id__in = userid) else: Q_include &= Q(id__in = userid) self.updated = True else: ## Select users based on all other criteria that was entered for field in ['username','last_name','first_name', 'email']: if criteria.get(field, '').strip(): # Check that it's a valid regular expression try: rc = re.compile(criteria[field]) except: raise ESPError('Invalid search expression, please check your syntax: %s' % criteria[field], log=False) filter_dict = {'%s__iregex' % field: criteria[field]} if '%s__not' % field in criteria: Q_exclude &= Q(**filter_dict) else: Q_include &= Q(**filter_dict) self.updated = True if 'zipcode' in criteria and 'zipdistance' in criteria and \ len(criteria['zipcode'].strip()) > 0 and len(criteria['zipdistance'].strip()) > 0: try: zipc = ZipCode.objects.get(zip_code = criteria['zipcode']) except: raise ESPError('Zip code not found. This may be because you didn\'t enter a valid US zipcode. Tried: "%s"' % criteria['zipcode'], log=False) zipcodes = zipc.close_zipcodes(criteria['zipdistance']) # Excludes zipcodes within a certain radius, giving an annulus; can fail to exclude people who used to live outside the radius. # This may have something to do with the Q_include line below taking more than just the most recent profile. -ageng, 2008-01-15 if criteria.get('zipdistance_exclude', '').strip(): zipcodes_exclude = zipc.close_zipcodes(criteria['zipdistance_exclude']) zipcodes = [ zipcode for zipcode in zipcodes if zipcode not in zipcodes_exclude ] if len(zipcodes) > 0: Q_include &= Q(registrationprofile__contact_user__address_zip__in = zipcodes, registrationprofile__most_recent_profile=True) self.updated = True if criteria.get('states', '').strip(): state_codes = criteria['states'].strip().upper().split(',') if 'states__not' in criteria: Q_exclude &= Q(registrationprofile__contact_user__address_state__in = state_codes, registrationprofile__most_recent_profile=True) else: Q_include &= Q(registrationprofile__contact_user__address_state__in = state_codes, registrationprofile__most_recent_profile=True) self.updated = True if 'grade_min' in criteria: yog = ESPUser.YOGFromGrade(criteria['grade_min']) if yog != 0: Q_include &= Q(registrationprofile__student_info__graduation_year__lte = yog, registrationprofile__most_recent_profile=True) self.updated = True if 'grade_max' in criteria: yog = ESPUser.YOGFromGrade(criteria['grade_max']) if yog != 0: Q_include &= Q(registrationprofile__student_info__graduation_year__gte = yog, registrationprofile__most_recent_profile=True) self.updated = True if 'school' in criteria: school = criteria['school'] if school: Q_include &= (Q(studentinfo__school__icontains=school) | Q(studentinfo__k12school__name__icontains=school)) self.updated = True # Filter by graduation years if specifically looking for teachers. possible_gradyears = range(1920, 2020) if criteria.get('gradyear_min', '').strip(): try: gradyear_min = int(criteria['gradyear_min']) except: raise ESPError('Please enter a 4-digit integer for graduation year limits.', log=False) possible_gradyears = filter(lambda x: x >= gradyear_min, possible_gradyears) if criteria.get('gradyear_max', '').strip(): try: gradyear_max = int(criteria['gradyear_max']) except: raise ESPError('Please enter a 4-digit integer for graduation year limits.', log=False) possible_gradyears = filter(lambda x: x <= gradyear_max, possible_gradyears) if criteria.get('gradyear_min', None) or criteria.get('gradyear_max', None): Q_include &= Q(registrationprofile__teacher_info__graduation_year__in = map(str, possible_gradyears), registrationprofile__most_recent_profile=True) self.updated = True return Q_base & (Q_include & ~Q_exclude)
def profile_editor(request, prog_input=None, responseuponCompletion = True, role=''): """ Display the registration profile page, the page that contains the contact information for a student, as attached to a particular program """ from esp.users.models import K12School from esp.web.views.main import registration_redirect if prog_input is None: prog = None else: prog = prog_input curUser = request.user context = {'logged_in': request.user.is_authenticated() } context['user'] = request.user context['program'] = prog curUser.updateOnsite(request) # Get the profile form from the user's type, although we need to handle # a couple of extra possibilities for the 'role' variable. user_types = ESPUser.getAllUserTypes() additional_types = [['', {'label': 'Not specified', 'profile_form': 'UserContactForm'}], ['Administrator', {'label': 'Administrator', 'profile_form': 'UserContactForm'}], ] additional_type_labels = [x[0] for x in additional_types] # Handle all-lowercase versions of role being passed in by calling title() user_type_labels = [x[0] for x in user_types] if role.title() in user_type_labels: target_type = user_types[user_type_labels.index(role.title())][1] else: target_type = additional_types[additional_type_labels.index(role.title())][1] mod = __import__('esp.users.forms.user_profile', (), (), target_type['profile_form']) FormClass = getattr(mod, target_type['profile_form']) context['profiletype'] = role if request.method == 'POST' and 'profile_page' in request.POST: form = FormClass(curUser, request.POST) # Don't suddenly demand an explanation from people who are already student reps if curUser.hasRole("StudentRep"): if hasattr(form, 'repress_studentrep_expl_error'): form.repress_studentrep_expl_error() if form.is_valid(): new_data = form.cleaned_data regProf = RegistrationProfile.getLastForProgram(curUser, prog) if regProf.id is None: old_regProf = RegistrationProfile.getLastProfile(curUser) else: old_regProf = regProf for field_name in ['address_zip','address_city','address_street','address_state']: if field_name in new_data and new_data[field_name] != getattr(old_regProf.contact_user,field_name,False): new_data['address_postal'] = '' if new_data['address_postal'] == '': new_data['address_postal'] = False regProf.contact_user = ContactInfo.addOrUpdate(regProf, new_data, regProf.contact_user, '', curUser) regProf.contact_emergency = ContactInfo.addOrUpdate(regProf, new_data, regProf.contact_emergency, 'emerg_') if new_data.get('dietary_restrictions'): regProf.dietary_restrictions = new_data['dietary_restrictions'] if role == 'student': regProf.student_info = StudentInfo.addOrUpdate(curUser, regProf, new_data) regProf.contact_guardian = ContactInfo.addOrUpdate(regProf, new_data, regProf.contact_guardian, 'guard_') elif role == 'teacher': regProf.teacher_info = TeacherInfo.addOrUpdate(curUser, regProf, new_data) elif role == 'guardian': regProf.guardian_info = GuardianInfo.addOrUpdate(curUser, regProf, new_data) elif role == 'educator': regProf.educator_info = EducatorInfo.addOrUpdate(curUser, regProf, new_data) blah = regProf.__dict__ regProf.save() curUser.first_name = new_data['first_name'] curUser.last_name = new_data['last_name'] curUser.email = new_data['e_mail'] curUser.save() if responseuponCompletion == True: return registration_redirect(request) else: return True else: # Force loading the school back in if possible... replacement_data = form.data.copy() try: replacement_data['k12school'] = form.fields['k12school'].clean(form.data['k12school']).id except: pass form = FormClass(curUser, replacement_data) else: if prog_input is None: regProf = RegistrationProfile.getLastProfile(curUser) else: regProf = RegistrationProfile.getLastForProgram(curUser, prog) if regProf.id is None: regProf = RegistrationProfile.getLastProfile(curUser) new_data = {} if curUser.isStudent(): new_data['studentrep'] = curUser.groups.filter(name="StudentRep").exists() new_data['first_name'] = curUser.first_name new_data['last_name'] = curUser.last_name new_data['e_mail'] = curUser.email new_data = regProf.updateForm(new_data, role) if regProf.student_info and regProf.student_info.dob: new_data['dob'] = regProf.student_info.dob # Set default values for state fields state_fields = ['address_state', 'emerg_address_state'] state_tag_map = {} for field in state_fields: state_tag_map[field] = 'local_state' form = FormClass(curUser, initial=new_data, tag_map=state_tag_map) context['request'] = request context['form'] = form return render_to_response('users/profile.html', request, 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)
def query_from_postdata(self, program, data): """ Get a Q object for the targeted list of users from the POST data submitted on the main "comm panel" page """ def get_recipient_type(list_name): for user_type in Program.USER_TYPE_LIST_FUNCS: raw_lists = getattr(program, user_type)(True) if list_name in raw_lists: return user_type subquery = None if 'base_list' in data and 'recipient_type' in data: # Get the program-specific part of the query (e.g. which list to use) if data['recipient_type'] not in ESPUser.getTypes(): recipient_type = 'any' q_program = Q() else: if data['base_list'].startswith('all'): q_program = Q() recipient_type = data['recipient_type'] else: program_lists = getattr(program, data['recipient_type'].lower()+'s')(QObjects=True) q_program = program_lists[data['base_list']] """ Some program queries rely on UserBits, and since user types are also stored in UserBits we cannot store both of these in a single Q object. To compensate, we ignore the user type when performing a program-specific query. """ recipient_type = 'any' # Get the user-specific part of the query (e.g. ID, name, school) q_extra = self.query_from_criteria(recipient_type, data) ## Handle "combination list" submissions elif 'combo_base_list' in data: # Get an initial query from the supplied base list recipient_type, list_name = data['combo_base_list'].split(':') if list_name.startswith('all'): q_program = Q() else: q_program = getattr(program, recipient_type.lower()+'s')(QObjects=True)[list_name] # Apply Boolean filters # Base list will be intersected with any lists marked 'AND', and then unioned # with any lists marked 'OR'. checkbox_keys = map(lambda x: x[9:], filter(lambda x: x.startswith('checkbox_'), data.keys())) and_keys = map(lambda x: x[4:], filter(lambda x: x.startswith('and_'), checkbox_keys)) or_keys = map(lambda x: x[3:], filter(lambda x: x.startswith('or_'), checkbox_keys)) not_keys = map(lambda x: x[4:], filter(lambda x: x.startswith('not_'), checkbox_keys)) #if any keys concern the same field, we will place them into #a subquery and count occurrences #for the purpose of experimentation simply fix this to the record__event #as this could very well have different implications for other fields subqry_fieldmap = {'record__event':[]} for and_list_name in and_keys: user_type = get_recipient_type(and_list_name) if user_type: qobject = getattr(program, user_type)(QObjects=True)[and_list_name] if and_list_name in not_keys: q_program = q_program & ~qobject else: qobject_child = qobject.children[1] needs_subquery = False if isinstance(qobject_child, (list, tuple)): field_name, field_value = qobject.children[1] needs_subquery = field_name in subqry_fieldmap if needs_subquery: subqry_fieldmap[field_name].append(field_value) if not needs_subquery: q_program = q_program & qobject event_fields = subqry_fieldmap['record__event'] if event_fields: #annotation is needed to initiate group by #except that it causes the query to return two columns #so we call values at the end of the chain, however, #that results in multiple group by fields(causing the query to fail) #so, we assign a group by field, to force grouping by user_id subquery = ( Record .objects .filter(program=program,event__in=event_fields) .annotate(numusers=Count('user__id')) .filter(numusers=len(event_fields)) .values_list('user_id',flat=True) ) subquery.query.group_by = []#leave empty to strip out duplicate group by subquery = Q(pk__in=subquery) for or_list_name in or_keys: user_type = get_recipient_type(or_list_name) if user_type: qobject = getattr(program, user_type)(QObjects=True)[or_list_name] if or_list_name not in not_keys: q_program = q_program | qobject else: q_program = q_program | ~qobject # Get the user-specific part of the query (e.g. ID, name, school) q_extra = self.query_from_criteria(recipient_type, data) qobject = (q_extra & q_program & Q(is_active=True)) #strip out duplicate clauses # Note: in some cases, the children of the Q object are unhashable. # Keep these separate. clauses_hashable = [] clauses_unhashable = [] for clause in qobject.children: if isinstance(clause, Q) or (isinstance(clause, tuple) and isinstance(clause[1], collections.Hashable)): clauses_hashable.append(clause) else: clauses_unhashable.append(clause) qobject.children = list(set(clauses_hashable)) + clauses_unhashable if subquery: qobject = qobject & subquery return qobject
def __init__(self, user=None, *args, **kwargs): from esp.users.models import ESPUser super(StudentInfoForm, self).__init__(user, *args, **kwargs) self.allow_change_grade_level = Tag.getTag('allow_change_grade_level') ## All of these Tags may someday want to be made per-program somehow. ## We don't know the current program right now, though... show_studentrep_application = Tag.getTag('show_studentrep_application') if not show_studentrep_application: ## Only enable the Student Rep form optionally. del self.fields['studentrep'] if (not show_studentrep_application) or show_studentrep_application == "no_expl": del self.fields['studentrep_expl'] if not Tag.getTag('show_student_tshirt_size_options'): del self.fields['shirt_size'] del self.fields['shirt_type'] elif Tag.getTag('studentinfo_shirt_type_selection') == 'False': del self.fields['shirt_type'] if not Tag.getTag('show_student_vegetarianism_options'): del self.fields['food_preference'] # Allow grade range of students to be customized by a Tag (default is 7-12) self.fields['graduation_year'].choices = [('','')]+[(str(ESPUser.YOGFromGrade(x)), str(x)) for x in ESPUser.grade_options()] # Add user's current grade if it is out of range and they have already filled out the profile. if user and user.registrationprofile_set.count() > 0: user_grade = user.getGrade() grade_tup = (str(ESPUser.YOGFromGrade(user_grade)), str(user_grade)) if grade_tup not in self.fields['graduation_year'].choices: self.fields['graduation_year'].choices.insert(0, grade_tup) # Honor several possible Tags for customizing the fields that are displayed. if Tag.getTag('show_student_graduation_years_not_grades'): current_grad_year = self.ESPUser.current_schoolyear() new_choices = [] for x in self.fields['graduation_year'].choices: if len(x[0]) > 0: new_choices.append((str(x[0]), "%s (%sth grade)" % (x[0], x[1]))) else: new_choices.append(x) self.fields['graduation_year'].choices = new_choices if not Tag.getBooleanTag('student_profile_gender_field'): del self.fields['gender'] if not Tag.getTag('ask_student_about_transportation_to_program'): del self.fields['transportation'] if not Tag.getTag('allow_change_grade_level'): if 'initial' in kwargs: initial_data = kwargs['initial'] # Disable the age and grade fields if they already exist. if 'graduation_year' in initial_data and 'dob' in initial_data: self.fields['graduation_year'].widget.attrs['disabled'] = "true" self.fields['graduation_year'].required = False self.fields['dob'].widget.attrs['disabled'] = "true" self.fields['dob'].required = False # Add field asking about medical needs if directed by the Tag if Tag.getTag('student_medical_needs'): self.fields['medical_needs'].widget = forms.Textarea(attrs={'cols': 40, 'rows': 3}) else: del self.fields['medical_needs'] # The unmatched_school field is for students to opt out of selecting a K12School. # If we don't require a K12School to be selected, don't bother showing that field. if not Tag.getBooleanTag('require_school_field', default=False): del self.fields['unmatched_school'] self._user = user
def __init__(self, *args, **kwargs): super(OnSiteRegForm, self).__init__(*args, **kwargs) self.fields['grade'].choices = ( [('', '')] + [(x, x) for x in ESPUser.grade_options()])
def stats(prog): # Create a dictionary to assemble the output dictOut = { "stats": [] } classes = prog.classes().select_related() vitals = {'id': 'vitals'} class_num_list = [] class_num_list.append(("Total # of Classes", classes.distinct().count())) class_num_list.append(("Total # of Class Sections", prog.sections().select_related().distinct().count())) class_num_list.append(("Total # of Lunch Classes", classes.filter(category__category = "Lunch").filter(status=10).distinct().count())) class_num_list.append(("Total # of Classes <span style='color: #00C;'>Unreviewed</span>", classes.filter(status=0).distinct().count())) class_num_list.append(("Total # of Classes <span style='color: #0C0;'>Accepted</span>", classes.filter(status=10).distinct().count())) class_num_list.append(("Total # of Classes <span style='color: #C00;'>Rejected</span>", classes.filter(status=-10).distinct().count())) class_num_list.append(("Total # of Classes <span style='color: #990;'>Cancelled</span>", classes.filter(status=-20).distinct().count())) for ft in ClassFlagType.get_flag_types(prog): class_num_list.append(('Total # of Classes with the "%s" flag' % ft.name, classes.filter(flags__flag_type=ft).distinct().count())) vitals['classnum'] = class_num_list # Display pretty labels for teacher and student numbers teacher_labels_dict = {} for module in prog.getModules(): teacher_labels_dict.update(module.teacherDesc()) vitals['teachernum'] = [] ## Ew, queries in a for loop... ## Not much to be done about it, though; ## the loop is iterating over a list of independent queries and running each. teachers = prog.teachers() for key in teachers.keys(): if key in teacher_labels_dict: vitals['teachernum'].append((teacher_labels_dict[key], ## Unfortunately, teachers[key].filter(is_active = True).distinct().count())) else: vitals['teachernum'].append((key, teachers[key].filter(is_active = True).distinct().count())) student_labels_dict = {} for module in prog.getModules(): student_labels_dict.update(module.studentDesc()) vitals['studentnum'] = [] ## Ew, another set of queries in a for loop... ## Same justification, though. students = prog.students() for key in students.keys(): if key in student_labels_dict: vitals['studentnum'].append((student_labels_dict[key], students[key].filter(is_active = True).distinct().count())) else: vitals['studentnum'].append((key, students[key].filter(is_active = True).distinct().count())) timeslots = prog.getTimeSlots() vitals['timeslots'] = [] shours = 0.0 chours = 0.0 crhours = 0.0 ## Write this as a 'for' loop because PostgreSQL can't do it in ## one go without a subquery or duplicated logic, and Django ## doesn't have enough power to expose either approach directly. ## At least there aren't any queries in the for loop... ## (In MySQL, this could I believe be done with a minimally-painful extra() clause.) ## Also, since we're iterating over a big data set, use .values() ## minimize the number of objects that we're creating. ## One dict and two Decimals per row, as opposed to ## an Object per field and all kinds of stuff... for cls in prog.classes().exclude(category__category='Lunch').annotate(num_sections=Count('sections'), subject_duration=Sum('sections__duration'), subject_students=Sum('sections__enrolled_students')).values('num_sections', 'subject_duration', 'subject_students', 'class_size_max'): if cls['subject_duration']: chours += float(cls['subject_duration']) shours += float(cls['subject_duration']) * (float(cls['class_size_max']) if cls['class_size_max'] else 0) crhours += float(cls['subject_duration']) * float(cls['subject_students']) / float(cls['num_sections']) vitals["hournum"] = [] vitals["hournum"].append(("Total # of Class-Hours", chours)) vitals["hournum"].append(("Total # of Class-Student-Hours (capacity)", shours)) vitals["hournum"].append(("Total # of Class-Student-Hours (registered)", crhours)) ## Prefetch enough data that get_meeting_times() and num_students() don't have to hit the db curclasses = ClassSection.prefetch_catalog_data( ClassSection.objects .filter(parent_class__parent_program=prog) .select_related('parent_class', 'parent_class__category')) ## Is it really faster to do this logic in Python? ## It'd be even faster to just write a raw SQL query to do it. ## But this is probably good enough. timeslot_dict = defaultdict(list) timeslot_set = set(timeslots) for section in curclasses: for timeslot in set.intersection(timeslot_set, section.get_meeting_times()): timeslot_dict[timeslot].append(section) for timeslot in timeslots: curTimeslot = {'slotname': timeslot.short_description} curTimeslot['classcount'] = len(timeslot_dict[timeslot]) def student_count(clslist): lst = [0] + [x.num_students() for x in clslist if x.category.category != 'Lunch'] return reduce(operator.add, lst) def student_max_count(clslist): lst = [0] + [x.capacity for x in clslist if x.category.category != 'Lunch'] return reduce(operator.add, lst) curTimeslot['studentcount'] = { 'count': student_count(timeslot_dict[timeslot]), 'max_count': student_max_count(timeslot_dict[timeslot]) } vitals['timeslots'].append(curTimeslot) dictOut["stats"].append(vitals) shirt_data = {"id": "shirtnum"}; adminvitals_shirt = prog.getShirtInfo() shirt_data["sizes"] = adminvitals_shirt['shirt_sizes']; shirt_data["types"] = adminvitals_shirt['shirt_types']; shirt_data["data"] = adminvitals_shirt['shirts']; dictOut["stats"].append(shirt_data); Q_categories = Q(program=prog) crmi = prog.classregmoduleinfo if crmi.open_class_registration: Q_categories |= Q(pk=prog.open_class_category.pk) # Introduce a separate query to get valid categories, since the single query seemed to introduce duplicates program_categories = ClassCategories.objects.filter(Q_categories).distinct().values_list('id', flat=True) annotated_categories = ClassCategories.objects.filter(cls__parent_program=prog, cls__status__gte=0).annotate(num_subjects=Count('cls', distinct=True), num_sections=Count('cls__sections'), num_class_hours=Sum('cls__sections__duration')).order_by('-num_subjects').values('id', 'num_sections', 'num_subjects', 'num_class_hours', 'category').distinct() # Convert Decimal values to float for serialization for i in range(len(annotated_categories)): annotated_categories[i]['num_class_hours'] = float(annotated_categories[i]['num_class_hours']) dictOut["stats"].append({"id": "categories", "data": filter(lambda x: x['id'] in program_categories, annotated_categories)}) ## Calculate the grade data: grades = [i for i in range(prog.grade_min, prog.grade_max+1)] # We can't perfectly trust most_recent_profile, but it's good enough for stats students_grades = students['enrolled'].filter(registrationprofile__most_recent_profile=True) students_grades = students_grades.values_list('registrationprofile__student_info__graduation_year') students_grades = students_grades.annotate(Count('id', distinct=True)) grades_dict = {result[0]: result[1] for result in students_grades} grades_results = [] for g in grades: year = ESPUser.YOGFromGrade(g, ESPUser.program_schoolyear(prog)) grade_classes = classes.filter(status__gte=0, grade_min__lte=g, grade_max__gte=g) grade_sections = prog.sections().filter(status__gte=0, parent_class__in=grade_classes) grades_results.append({'grade': g, 'num_subjects': grade_classes.count(), 'num_sections': grade_sections.count(), 'num_students': grades_dict[year] if year in grades_dict else 0}) dictOut["stats"].append({"id": "grades", "data": grades_results}) # Add SplashInfo statistics if our program has them splashinfo_data = {} splashinfo_modules = filter(lambda x: isinstance(x, SplashInfoModule), prog.getModules('learn')) if len(splashinfo_modules) > 0: splashinfo_module = splashinfo_modules[0] tag_data = Tag.getProgramTag('splashinfo_choices', prog) if tag_data: splashinfo_choices = json.loads(tag_data) else: splashinfo_choices = {'lunchsat': SplashInfoForm.default_choices, 'lunchsun': SplashInfoForm.default_choices} for key in splashinfo_choices: counts = {} for item in splashinfo_choices[key]: filter_kwargs = {'program': prog} filter_kwargs[key] = item[0] counts[item[1]] = SplashInfo.objects.filter(**filter_kwargs).distinct().count() splashinfo_data[key] = counts splashinfo_data['siblings'] = { 'yes': SplashInfo.objects.filter(program=prog, siblingdiscount=True).distinct().count(), 'no': SplashInfo.objects.filter(program=prog).exclude(siblingdiscount=True).distinct().count() } dictOut["stats"].append({"id": "splashinfo", "data": splashinfo_data}) # Add accounting stats pac = ProgramAccountingController(prog) (num_payments, total_payment) = pac.payments_summary() accounting_data = { 'num_payments': num_payments, # We need to convert to a float in order for json to serialize it. # Since we're not doing any computation client-side with these # numbers, this doesn't cause accuracy issues. If the # total_payment is None, just coerce it to zero for display # purposes. 'total_payments': float(total_payment or 0), } dictOut["stats"].append({"id": "accounting", "data": accounting_data}) return dictOut
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.enroll_orig = numpy.zeros((self.num_students, self.num_sections, self.num_timeslots), dtype=numpy.bool) self.enroll_final = numpy.zeros((self.num_students, self.num_sections, self.num_timeslots), dtype=numpy.bool) self.request = numpy.zeros((self.num_students, self.num_sections, self.num_timeslots), dtype=numpy.bool) self.waitlist = [numpy.zeros((self.num_students, self.num_sections, self.num_timeslots), dtype=numpy.bool) for i in range(self.priority_limit+1)] self.section_schedules = numpy.zeros((self.num_sections, self.num_timeslots), dtype=numpy.bool) self.section_capacities = numpy.zeros((self.num_sections,), dtype=numpy.int32) self.section_scores = numpy.zeros((self.num_sections,), dtype=numpy.int32) self.same_subject = numpy.zeros((self.num_sections, self.num_sections), dtype=numpy.bool) self.section_conflict = numpy.zeros((self.num_sections, self.num_sections), dtype=numpy.bool) # is this a section that takes place in the same timeblock # Get student, section, timeslot IDs and prepare lookup table (self.student_ids, self.student_indices) = self.get_ids_and_indices(self.students) (self.section_ids, self.section_indices) = self.get_ids_and_indices(self.sections) (self.timeslot_ids, self.timeslot_indices) = self.get_ids_and_indices(self.timeslots) self.parent_classes = numpy.array(self.sections.values_list('parent_class__id', flat=True)) self.student_not_checked_in = numpy.zeros((self.num_students,), dtype=numpy.bool) self.student_not_checked_in[self.student_indices[self.students_not_checked_in]] = True # 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.timeslots: 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 old enrollment matrix enroll_regs = StudentRegistration.objects.filter(self.Q_EN).values_list('user__id', 'section__id', 'section__meeting_times__id').distinct() era = numpy.array(enroll_regs, dtype=numpy.uint32) try: self.enroll_orig[self.student_indices[era[:, 0]], self.section_indices[era[:, 1]], self.timeslot_indices[era[:, 2]]] = True except IndexError: pass self.student_not_checked_in[numpy.transpose(numpy.nonzero(True-self.enroll_orig.any(axis=(1,2))))] = True # Populate old enrollment matrix request_regs = StudentRegistration.objects.filter(self.Q_REQ).values_list('user__id', 'section__id', 'section__meeting_times__id').distinct() rra = numpy.array(request_regs, dtype=numpy.uint32) try: self.request[self.student_indices[rra[:, 0]], self.section_indices[rra[:, 1]], self.timeslot_indices[rra[:, 2]]] = True except IndexError: pass # Populate waitlist matrix waitlist_regs = [StudentRegistration.objects.filter(self.Q_WAIT[i]).values_list('user__id', 'section__id', 'section__meeting_times__id').distinct() for i in range(self.priority_limit+1)] wra = [numpy.array(waitlist_regs[i], dtype=numpy.uint32) for i in range(self.priority_limit+1)] self.waitlist[0][:,:,:] = True for i in range(1, self.priority_limit+1): try: self.waitlist[i][self.student_indices[wra[i][:, 0]], self.section_indices[wra[i][:, 1]], self.timeslot_indices[wra[i][:, 2]]] = True self.waitlist[0][self.student_indices[wra[i][:, 0]], self.section_indices[wra[i][:, 1]], self.timeslot_indices[wra[i][:, 2]]] = False except IndexError: pass # Populate section schedule section_times = numpy.array(self.sections.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 for i in range(self.num_sections): group_ids = numpy.nonzero(self.parent_classes == self.parent_classes[i])[0] self.same_subject[numpy.meshgrid(group_ids, group_ids)] = True sec_times = numpy.transpose(numpy.nonzero(self.section_schedules[i, :])) for [ts_ind,] in sec_times: self.section_conflict[numpy.transpose(numpy.nonzero(self.section_schedules[:, ts_ind])), i] = True self.section_conflict[i, numpy.transpose(numpy.nonzero(self.section_schedules[:, ts_ind]))] = True self.section_conflict[i, i] = False # Populate section grade limits self.section_grade_min = numpy.array(self.sections.values_list('parent_class__grade_min', flat=True), dtype=numpy.uint32) self.section_grade_max = numpy.array(self.sections.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.program_schoolyear(self.program) - gradyear_pairs[:, 1] # Find section capacities (TODO: convert to single query) for sec in self.sections: sec_ind = self.section_indices[sec.id] self.section_capacities[sec_ind] = sec.capacity - sec.num_students() self.section_capacities[sec_ind] += numpy.count_nonzero((self.enroll_orig[:, sec_ind, self.section_schedules[sec_ind,:]].any(axis=1) * self.request[:,:,self.section_schedules[sec_ind,:]].any(axis=(1,2)))) # number enrolled but want to switch out self.enroll_final[numpy.transpose(numpy.nonzero((self.enroll_orig[:, sec_ind, self.section_schedules[sec_ind,:]].any(axis=1) * (True - self.request[:,:,self.section_schedules[sec_ind,:]].any(axis=(1,2)))))), sec_ind, self.section_schedules[sec_ind,:]] = True self.section_scores[sec_ind] = -self.section_capacities[sec_ind] self.section_scores[sec_ind] += numpy.count_nonzero(self.request[:, sec_ind, :].any(axis=1)) # number who want to switch in self.section_capacities_orig = numpy.copy(self.section_capacities) self.section_scores_orig = numpy.copy(self.section_scores) self.enroll_final_orig = numpy.copy(self.enroll_final) self.clear_assignments()
def onsite_create(self, request, tl, one, two, module, extra, prog): if request.method == 'POST': form = OnSiteRegForm(request.POST) if form.is_valid(): new_data = form.cleaned_data username = ESPUser.get_unused_username(new_data['first_name'], new_data['last_name']) new_user = ESPUser.objects.create_user(username = username, first_name = new_data['first_name'], last_name = new_data['last_name'], email = new_data['email']) self.student = new_user regProf = RegistrationProfile.getLastForProgram(new_user, self.program) contact_user = ContactInfo(first_name = new_user.first_name, last_name = new_user.last_name, e_mail = new_user.email, user = new_user) contact_user.save() regProf.contact_user = contact_user student_info = StudentInfo(user = new_user, graduation_year = ESPUser.YOGFromGrade(new_data['grade'], ESPUser.program_schoolyear(self.program))) try: if isinstance(new_data['k12school'], K12School): student_info.k12school = new_data['k12school'] else: if isinstance(new_data['k12school'], int): student_info.k12school = K12School.objects.get(id=int(new_data['k12school'])) else: student_info.k12school = K12School.objects.filter(name__icontains=new_data['k12school'])[0] except: student_info.k12school = None student_info.school = new_data['school'] if not student_info.k12school else student_info.k12school.name student_info.save() regProf.student_info = student_info regProf.save() if new_data['paid']: self.createBit('paid') self.updatePaid(True) else: self.updatePaid(False) self.createBit('Attended') if new_data['medical']: self.createBit('Med') if new_data['liability']: self.createBit('Liab') self.createBit('OnSite') new_user.groups.add(Group.objects.get(name="Student")) new_user.recoverPassword() return render_to_response(self.baseDir()+'reg_success.html', request, { 'student': new_user, 'retUrl': '/onsite/%s/classchange_grid?student_id=%s' % (self.program.getUrlBase(), new_user.id) }) else: form = OnSiteRegForm() return render_to_response(self.baseDir()+'reg_info.html', request, {'form':form})
def process(self): """Process this request, creating TextOfEmail and EmailRequest objects. It is the caller's responsibility to call this only on unprocessed MessageRequests. """ # figure out who we're sending from... if self.sender is not None and len(self.sender.strip()) > 0: send_from = self.sender else: if self.creator is not None: send_from = '%s <%s>' % (self.creator.name(), self.creator.email) else: send_from = 'ESP Web Site <*****@*****.**>' users = self.recipients.getList(ESPUser).distinct() sendto_fn = self.get_sendto_fn_callable(self.sendto_fn_name) # go through each user and parse the text...then create the proper # emailrequest and textofemail object for user in users: subject = self.parseSmartText(self.subject, user) msgtext = self.parseSmartText(self.msgtext, user) # For each user, create an EmailRequest and a TextOfEmail # for each address given by the output of the sendto function. for address_pair in sendto_fn(user): newemailrequest = {'target': user, 'msgreq': self} send_to = ESPUser.email_sendto_address(*address_pair) newtxt = { 'send_to': send_to, 'send_from': send_from, 'subject': subject, 'msgtext': msgtext, 'created_at': self.created_at, 'defaults': {'sent': None}, } # Use get_or_create so that, if this send_to address is # already receiving the exact same email, it doesn't need to # get sent a second time. # This is useful to de-duplicate announcement emails for # people with multiple accounts, or for preventing a user # from receiving a duplicate when a message request needs to # be resent after a bug prevented it from being received by # all recipients the first time. newtxt, created = TextOfEmail.objects.get_or_create(**newtxt) if not created: logger.warning('Skipped duplicate creation of message to %s for message request %d: %s', send_to, self.id, self.subject) newemailrequest['textofemail'] = newtxt EmailRequest.objects.get_or_create(**newemailrequest) # Mark ourselves processed. We don't have to worry about the DB # falling over between the above writes and this one, because the whole # assembly is in a transaction. self.processed = True self.save() logger.info('Prepared e-mails to send for message request %d: %s', self.id, self.subject)