def post(self, *args, **kwargs): # block POSTs from most people. userrole = ASHMCAppointment.get_current_highest(self.request.user) minimum_role = ASHMCRole.objects.get(title=ASHMCRole.COUNCIL_ROLES[2]) if userrole < minimum_role: if "Class President" not in userrole.title: raise PermissionDenied() form_class = self.get_form_class() # This setting to None is a hack to make the get_form call work. self.object = None form = self.get_form(form_class) if not form.is_valid(): return self.form_invalid(form) print form.cleaned_data # The measure itself is valid; create it. new_measure = Measure.objects.create( name=form.cleaned_data['name'], vote_start=form.cleaned_data['vote_start'], vote_end=form.cleaned_data['vote_end'], summary=form.cleaned_data['summary'], quorum=form.cleaned_data['quorum'], is_open=form.cleaned_data['is_open'], ) logger.info("Created measure %d", new_measure.id) # This doesn't currently allow banned_accounts to be added. You need # use the regular admin for that. if isinstance(self.request.user.highest_ashmc_role.cast(), DormPresident): # Dorm presidents can only send measures to their dorm. logger.debug("dorm president dorm restriction") real_role = self.request.user.highest_ashmc_role.cast() dorm_restrictions = [real_role.dorm] elif self.request.user.highest_ashmc_role > ASHMCRole.objects.get( title=ASHMCRole.COUNCIL_ROLES[3]): logger.debug("unrestricted dorm restriction") # VP and president can restrict dorm as they choose. dorm_restrictions = Dorm.objects.filter( pk__in=self.request.POST.getlist('dorms')) else: logger.debug("no dorm restriction allowed") dorm_restrictions = [] if self.request.user.highest_ashmc_role.title.endswith( "Class President"): logger.debug("Enacting class-president restriction") # Year-based class presidents can only send measure to their constituencies. if self.request.user.highest_ashmc_role.title.startswith("Senior"): year_restrictions = [GradYear.senior_class()] elif self.request.user.highest_ashmc_role.title.startswith( "Junior"): year_restrictions = [GradYear.senior_class() - 1] elif self.request.user.highest_ashmc_role.title.startswith( "Sophomore"): year_restrictions = [GradYear.senior_class() - 2] else: year_restrictions = [GradYear.senior_class() - 3] else: year_restrictions = GradYear.objects.filter( pk__in=self.request.POST.getlist('gradyears')) # Update the Restrictions object for this new_measure. restrictions = new_measure.restrictions restrictions.gradyears.add(*[gy for gy in year_restrictions]) restrictions.dorms.add(*[d for d in dorm_restrictions]) # Now, ballot creation. # Ballots fields all look like r"(\d+)_.*". # There will always be at least one ballot; gather all the specified # attributes in a ballots_dict, to be used later to create the actual ballots # and candidates. ballots_dict = {} for key in self.request.POST: if not re.match(r"^\d+_", key): continue if self.request.POST[key] == "on": keyval = True else: keyval = self.request.POST[key] ballot_sep_index = key.index('_') ballot_num = int(key[:ballot_sep_index]) # create an empty dict with ballot num as key if it doesn't already exist. ballots_dict.setdefault(ballot_num, {}) key_rest = key[ballot_sep_index + 1:] if re.match(r"\d+_", key_rest): # this is a candidate field -- they will always start with # r"\d+_\d+_" ballots_dict[ballot_num].setdefault('candidates', {}) candidate_sep_index = key_rest.index('_') candidate_num = int(key_rest[:candidate_sep_index]) key_rest_rest = key_rest[candidate_sep_index + 1:] ballots_dict[ballot_num]['candidates'].setdefault( candidate_num, {}) ballots_dict[ballot_num]['candidates'][candidate_num][ key_rest_rest] = keyval else: # this is a ballot field. ballots_dict[ballot_num][key_rest] = keyval for ballot_num in ballots_dict: ballot_dict = ballots_dict[ballot_num] # sanitize ballot info for key, val in ballot_dict.items(): if val == "": del ballot_dict[key] if "can_abstain" not in ballot_dict: ballot_dict["can_abstain"] = False candidate_info = ballot_dict.pop('candidates', {}) ballot = Ballot.objects.create(measure=new_measure, **ballot_dict) logger.info("M%d: created ballot %d", new_measure.id, ballot.id) for candidate_num in candidate_info.keys(): candidate_dict = candidate_info[candidate_num] is_person = candidate_dict.pop('is_person', False) if is_person: usernames = candidate_dict['title'].split(' ') try: # Only support username students = Student.objects.filter( user__username__in=usernames) # if there's any problems, give up and create a normal # candidate. if not students: logger.warn("Could not find usernames: {}".format( usernames)) raise Student.DoesNotExist( "Could not find usernames: {}".format( usernames)) elif len(students) != len(usernames): logger.warn( "Could not find all usernames: {} (found {})". format(usernames, students)) raise Student.DoesNotExist( "Could not find all usernames: {} (found {})". format(usernames, students)) candidate = PersonCandidate.objects.create( ballot=ballot, **candidate_dict) logger.info("M%dB%d: created person candidate for %s", new_measure.id, ballot.id, students) for student in students: CandidateUser.objects.create( user=student.user, person_candidate=candidate, ) except Student.DoesNotExist: logger.warn( "M%dB%d: creating fallback candidate (instead of person candidate)", new_measure.id, ballot.id) candidate = Candidate.objects.create(ballot=ballot, **candidate_dict) print 'new candy keys:', candidate_info.keys() else: candidate = Candidate.objects.create(ballot=ballot, **candidate_dict) logger.info("M%dB%d: created candidate %d", new_measure.id, ballot.id, candidate.id) # Finally, take them to the measure list. return redirect('measure_list')
def handle(self, *args, **kwargs): if len(args) != 1: raise CommandError("This command accepts only one argument") try: workbook = xlrd.open_workbook(args[0]) except IOError: raise CommandError("Couldn't open roster: {}".format(args[0])) s = workbook.sheets()[0] # TODO: make this more programmatic? FIELD_ORDERING = settings.ROSTER_FIELD_ORDERING senior = GradYear.senior_class(sem=Semester.objects.get( half=kwargs['semester'], year=kwargs['year'])) logger.info("Senior year: %s", senior) CLASS_TO_GRADYEAR = { 'FE': senior + 3, # Freshmen have three codes 'FF': senior + 3, 'FR': senior + 3, 'SO': senior + 2, 'JR': senior + 1, 'SR': senior, } # Initialize and bind to the LDAP connection lconn = ldap.initialize(uri=settings.AUTH_LDAP_SERVER_URI, ) lconn.simple_bind_s( who=settings.AUTH_LDAP_BIND_DN, cred=settings.AUTH_LDAP_BIND_PASSWORD, ) # get hmc for easy access later hmc = Campus.objects.get(code='HM') this_sem, _ = Semester.objects.get_or_create( year=kwargs['year'], half=kwargs['semester'], ) logger.info("Semester: %s", this_sem) active_users = [] for r in xrange(settings.ROSTER_ROW_START, s.nrows): row = s.row(r) try: gradyear = CLASS_TO_GRADYEAR[row[FIELD_ORDERING.index( 'Class')].value] except KeyError: logger.error("%d No such class: %s", r, row[FIELD_ORDERING.index('Class')].value) continue # Skip people who've already graduated - we don't care about them if gradyear < CLASS_TO_GRADYEAR['SR'] and not kwargs['old_data']: continue email = row[FIELD_ORDERING.index('Email')].value try: new_user = User.objects.get(email=email, ) except ObjectDoesNotExist: # Check LDAP for user student_results = lconn.search_s( "OU=Academic Students,DC=HMC,DC=EDU", ldap.SCOPE_SUBTREE, filterstr="(mail={})".format(email, )) if len(student_results) < 1: logger.error("%d Couldn't find user with email %s", r, email) continue elif len(student_results) > 1: logger.error("%d Multiple students matching email %s", r, email) continue ldap_student = student_results[0][1] try: new_user = User.objects.create_user( username=ldap_student['sAMAccountName'][0], email=email, ) except Exception: new_user = User.objects.get( username=ldap_student['sAMAccountName'][0], ) # In case they were previously inactivated... new_user.is_active = True new_user.first_name = ldap_student['givenName'][0] new_user.last_name = ldap_student['sn'][0] new_user.save() # keep track of which users we HAVE seen this time through active_users += [new_user.id] new_student, _ = Student.objects.get_or_create( user=new_user, class_of=gradyear, at=hmc, studentid=None, ) dormcode = row[FIELD_ORDERING.index('Dorm')].value.split(' ') if dormcode[0] == '': logger.error("%d Couldn't match dormcode %s", r, dormcode) continue # Roster has CGUA, whereas DB has CGA. if dormcode[0].startswith("CGU"): dormcode = "CG{}".format(dormcode[0][-1]) else: dormcode = dormcode[0] try: dorm = Dorm.all_objects.get(code__iexact=dormcode) except ObjectDoesNotExist: # If all else fails, see if there's a name match logger.warn("No such code %s - trying name match", dormcode) try: dorm = Dorm.all_objects.get(name__istartswith=dormcode) except (ObjectDoesNotExist, MultipleObjectsReturned): logger.error( "{} ldap population failed for {} (on failed dorm lookup {}) - assuming OFF" .format(r, new_user, dormcode), ) dorm = Dorm.objects.get(code="OFF") if dorm.code == "OFF": room = DormRoom.objects.get( dorm=dorm, number="Symbolic Room", ) else: room, _ = DormRoom.objects.get_or_create( dorm=dorm, number=row[FIELD_ORDERING.index("Room")].value, ) if dorm.code in Dorm.all_objects.filter(official_dorm=False).values_list('code', flat=True)\ and dorm.code != "ABR": # If they're off-campus, make sure they're 'symbollically' # a part of the Offcampus dorm for voting purposes. symoff, _ = DormRoom.objects.get_or_create( dorm__code="OFF", number="Symbolic Room", ) # Symroom is going to be full of people. symroomur, _ = UserRoom.objects.get_or_create( user=new_user, room=symoff, ) symroomur.semesters.add(this_sem) logger.info("Created symoblic room entry for %s", new_user) ur, _ = UserRoom.objects.get_or_create( user=new_user, room=room, ) ur.semesters.add(this_sem) # inactivate missing users - except the super. for user in User.objects.exclude(is_superuser=True).exclude( id__in=active_users): logger.info("Inactivating {}".format(user.username)) user.is_active = False user.save()
def handle(self, *args, **kwargs): if len(args) != 1: raise CommandError("This command accepts only one argument") try: workbook = xlrd.open_workbook(args[0]) except IOError: raise CommandError("Couldn't open roster: {}".format(args[0])) s = workbook.sheets()[0] # TODO: make this more programmatic? FIELD_ORDERING = settings.ROSTER_FIELD_ORDERING senior = GradYear.senior_class( sem=Semester.objects.get(half=kwargs['semester'], year=kwargs['year']) ) logger.info("Senior year: %s", senior) CLASS_TO_GRADYEAR = { 'FE': senior + 3, # Freshmen have three codes 'FF': senior + 3, 'FR': senior + 3, 'SO': senior + 2, 'JR': senior + 1, 'SR': senior, } # Initialize and bind to the LDAP connection lconn = ldap.initialize( uri=settings.AUTH_LDAP_SERVER_URI, ) lconn.simple_bind_s( who=settings.AUTH_LDAP_BIND_DN, cred=settings.AUTH_LDAP_BIND_PASSWORD, ) # get hmc for easy access later hmc = Campus.objects.get(code='HM') this_sem, _ = Semester.objects.get_or_create( year=kwargs['year'], half=kwargs['semester'], ) logger.info("Semester: %s", this_sem) active_users = [] for r in xrange(settings.ROSTER_ROW_START, s.nrows): row = s.row(r) try: gradyear = CLASS_TO_GRADYEAR[row[FIELD_ORDERING.index('Class')].value] except KeyError: logger.error("%d No such class: %s", r, row[FIELD_ORDERING.index('Class')].value) continue # Skip people who've already graduated - we don't care about them if gradyear < CLASS_TO_GRADYEAR['SR'] and not kwargs['old_data']: continue email = row[FIELD_ORDERING.index('Email')].value try: new_user = User.objects.get( email=email, ) active_users += [new_user.id] except ObjectDoesNotExist: # Check LDAP for user student_results = lconn.search_s( "OU=Academic Students,DC=HMC,DC=EDU", ldap.SCOPE_SUBTREE, filterstr="(mail={})".format( email, ) ) if len(student_results) < 1: logger.error("%d Couldn't find user with email %s", r, email) continue elif len(student_results) > 1: logger.error("%d Multiple students matching email %s", r, email) continue ldap_student = student_results[0][1] try: new_user = User.objects.create_user( username=ldap_student['sAMAccountName'][0], email=email, ) except Exception: new_user = User.objects.get( username=ldap_student['sAMAccountName'][0], ) # In case they were previously inactivated... new_user.is_active = True new_user.first_name = ldap_student['givenName'][0] new_user.last_name = ldap_student['sn'][0] new_user.save() # keep track of which users we HAVE seen this time through active_users += [new_user.id] new_student, _ = Student.objects.get_or_create( user=new_user, class_of=gradyear, at=hmc, studentid=None, ) dormcode = row[FIELD_ORDERING.index('Dorm')].value.split(' ') if dormcode[0] == '': logger.error("%d Couldn't match dormcode %s", r, dormcode) continue # Roster has CGUA, whereas DB has CGA. if dormcode[0].startswith("CGU"): dormcode = "CG{}".format(dormcode[0][-1]) else: dormcode = dormcode[0] try: dorm = Dorm.all_objects.get(code__iexact=dormcode) except ObjectDoesNotExist: # If all else fails, see if there's a name match logger.warn("No such code %s - trying name match", dormcode) try: dorm = Dorm.all_objects.get(name__istartswith=dormcode) except (ObjectDoesNotExist, MultipleObjectsReturned): logger.error( "{} ldap population failed for {} (on failed dorm lookup {}) - assuming OFF".format(r, new_user, dormcode), ) dorm = Dorm.objects.get(code="OFF") if dorm.code == "OFF": room = DormRoom.objects.get( dorm=dorm, number="Symbolic Room", ) else: number = row[FIELD_ORDERING.index("Room")].value, try: number = int(number) except ValueError: number = str(number) room, _ = DormRoom.objects.get_or_create( dorm=dorm, number=number, ) if dorm.code in Dorm.all_objects.filter(official_dorm=False).values_list('code', flat=True)\ and dorm.code != "ABR": # If they're off-campus, make sure they're 'symbollically' # a part of the Offcampus dorm for voting purposes. symoff, _ = DormRoom.objects.get_or_create( dorm__code="OFF", number="Symbolic Room", ) # Symroom is going to be full of people. symroomur, _ = UserRoom.objects.get_or_create( user=new_user, room=symoff, ) symroomur.semesters.add(this_sem) logger.info("Created symoblic room entry for %s", new_user) ur, _ = UserRoom.objects.get_or_create( user=new_user, room=room, ) ur.semesters.add(this_sem) # inactivate missing users - except the super. for user in User.objects.exclude(is_superuser=True).exclude(id__in=active_users): logger.info("Inactivating {}".format(user.username)) user.is_active = False user.save()
def handle(self, *args, **kwargs): if len(args) != 1: raise CommandError("This command accepts only one argument") try: workbook = xlrd.open_workbook(args[0]) except IOError: raise CommandError("Couldn't open workbook: {}".format(args[0])) s = workbook.sheets()[0] # On what row does the actual information start? ROSTER_ROW_START = 3 # TODO: make this more programmatic? FIELD_ORDERING = [ 'ID', 'Fullname', 'Nickname', 'Class', 'Dorm', 'Room', 'Phonenumber', 'Email Address', ] senior = GradYear.senior_class( sem=Semester.objects.get(half=kwargs['semester'], year=kwargs['year']) ).year CLASS_TO_GRADYEAR = { 'FE': senior + 3, 'FF': senior + 3, 'FR': senior + 3, 'SO': senior + 2, 'JR': senior + 1, 'SR': senior, } for r in xrange(ROSTER_ROW_START, s.nrows): row = s.row(r) year = CLASS_TO_GRADYEAR[row[FIELD_ORDERING.index('Class')].value] if year < GradYear.senior_class().year and not kwargs['old_data']: continue gradyear, _ = GradYear.objects.get_or_create( year=year, ) print row hmc = Campus.objects.get(code='HM') fullname = row[FIELD_ORDERING.index('Fullname')].value l_f_m_name = fullname.split(', ') last_name = l_f_m_name[0] f_m_name = ', '.join(l_f_m_name[1:]).split(' ') first_name = f_m_name[0] middle_name = '' temp_password = User.objects.make_random_password() try: new_user = User.objects.get(email=row[FIELD_ORDERING.index('Email Address')].value.lower().replace('hmc.edu', 'g.hmc.edu')) except ObjectDoesNotExist: new_user = User.objects.create_user( username=row[FIELD_ORDERING.index('Email Address')].value.lower().replace('hmc.edu', 'g.hmc.edu'), email=row[FIELD_ORDERING.index('Email Address')].value.lower().replace('hmc.edu', 'g.hmc.edu'), password=temp_password, ) new_user.first_name = first_name new_user.last_name = last_name new_user.save() studentid = int(row[FIELD_ORDERING.index('ID')].value), studentid = None new_student, _ = Student.objects.get_or_create( user=new_user, class_of=gradyear, at=hmc, studentid=studentid, ) new_student.middle_name = middle_name new_student.temp_pass = temp_password new_student.save() dormname = row[FIELD_ORDERING.index('Dorm')].value.split(' ') if dormname[0] != '': if dormname[0] == "CGU": dormname = ' '.join(dormname) else: dormname = dormname[0] dorm = Dorm.objects.get(name__startswith=dormname) room, _ = DormRoom.objects.get_or_create( dorm=dorm, number=row[FIELD_ORDERING.index("Room")].value, ) ur, _ = UserRoom.objects.get_or_create( user=new_user, room=room, ) ur.semesters.add(Semester.objects.get(half=kwargs['semester'], year=int(kwargs['year'])))
def create_user_related_things(*args, **kwargs): if 'user' not in kwargs or 'ldap_user' not in kwargs: return new_user = kwargs['user'] print new_user, new_user.email # don't repopulate if we've already done the dance. if Student.objects.filter(user=new_user).count(): logger.debug("skipping student {}".format(new_user)) return logger.info("new student {}".format(new_user)) try: this_sem = Semester.get_this_semester() workbook = xlrd.open_workbook(settings.ROSTER_DIRECTORY + "{}.xlsx".format( this_sem.verbose_unicode() )) except IOError: logger.error("could not open workbook {}".format(this_sem.verbose_unicode())) return s = workbook.sheets()[0] # On what row does the actual information start? ROSTER_ROW_START = settings.ROSTER_ROW_START # TODO: make this more programmatic? FIELD_ORDERING = settings.ROSTER_FIELD_ORDERING senior = GradYear.senior_class( sem=this_sem, ).year if settings.DEBUG: print "\tsenior year:", senior CLASS_TO_GRADYEAR = { 'FE': senior + 3, 'FF': senior + 3, 'FR': senior + 3, 'SO': senior + 2, 'JR': senior + 1, 'SR': senior, } try: for r in xrange(ROSTER_ROW_START, s.nrows): row = s.row(r) if row[FIELD_ORDERING.index('Email')].value != new_user.email: logger.debug("\tSkipping row", r, row[FIELD_ORDERING.index('Email')].value) continue logger.debug("creating user-related things...") year = CLASS_TO_GRADYEAR[row[FIELD_ORDERING.index('Class')].value] gradyear, _ = GradYear.objects.get_or_create( year=year, ) hmc = Campus.objects.get(code='HM') studentid = None new_student, _ = Student.objects.get_or_create( user=new_user, class_of=gradyear, at=hmc, studentid=studentid, phonenumber=row[FIELD_ORDERING.index('Phone')].value, #birthdate=datetime.datetime.strptime(row[FIELD_ORDERING.index('Birthdate')].value, '%b %d, %Y').date(), ) dormcode = row[FIELD_ORDERING.index('Dorm')].value.split(' ') if dormcode[0] != '': # Roster has CGUA, whereas DB has CGA. if dormcode[0] == "CGU": dormcode = ' '.join(dormcode) else: dormcode = dormcode[0] try: dorm = Dorm.objects.get(code__iexact=dormcode) except ObjectDoesNotExist: try: dorm = Dorm.objects.get(name__istartswith=dormcode) except (ObjectDoesNotExist, MultipleObjectsReturned): logger.error( "ldap population failed for {} (on failed dorm lookup {})".format(new_user, dormcode) ) return room, _ = DormRoom.objects.get_or_create( dorm=dorm, number=row[FIELD_ORDERING.index("Room")].value, ) if dorm.code in Dorm.all_objects.filter(official_dorm=False).values_list('code', flat=True)\ and dorm.code != "ABR": # If they're off-campus, make sure they're 'symbollically' # a part of the Offcampus dorm. symoff, _ = DormRoom.objects.get_or_create( dorm__code="OFF", number="Symbolic Room", ) # Symroom is going to be full of people. symroomur, _ = UserRoom.objects.get_or_create( user=new_user, room=symoff, ) symroomur.semesters.add(this_sem) ur, _ = UserRoom.objects.get_or_create( user=new_user, room=room, ) ur.semesters.add(this_sem) return except Exception, e: # Don't interrupt core service, no matter what. logger.error("caught unhandled exception {}: {}".format(e, e.message)) return
def handle(self, *args, **kwargs): if len(args) != 1: raise CommandError("This command accepts only one argument") try: workbook = xlrd.open_workbook(args[0]) except IOError: raise CommandError("Couldn't open workbook: {}".format(args[0])) s = workbook.sheets()[0] # On what row does the actual information start? ROSTER_ROW_START = 3 # TODO: make this more programmatic? FIELD_ORDERING = ["ID", "Fullname", "Nickname", "Class", "Dorm", "Room", "Phonenumber", "Email Address"] senior = GradYear.senior_class(sem=Semester.objects.get(half=kwargs["semester"], year=kwargs["year"])).year CLASS_TO_GRADYEAR = { "FE": senior + 3, "FF": senior + 3, "FR": senior + 3, "SO": senior + 2, "JR": senior + 1, "SR": senior, } for r in xrange(ROSTER_ROW_START, s.nrows): row = s.row(r) year = CLASS_TO_GRADYEAR[row[FIELD_ORDERING.index("Class")].value] if year < GradYear.senior_class().year and not kwargs["old_data"]: continue gradyear, _ = GradYear.objects.get_or_create(year=year) print row hmc = Campus.objects.get(code="HM") fullname = row[FIELD_ORDERING.index("Fullname")].value l_f_m_name = fullname.split(", ") last_name = l_f_m_name[0] f_m_name = ", ".join(l_f_m_name[1:]).split(" ") first_name = f_m_name[0] middle_name = "" temp_password = User.objects.make_random_password() try: new_user = User.objects.get( email=row[FIELD_ORDERING.index("Email Address")].value.lower().replace("hmc.edu", "g.hmc.edu") ) except ObjectDoesNotExist: new_user = User.objects.create_user( username=row[FIELD_ORDERING.index("Email Address")].value.lower().replace("hmc.edu", "g.hmc.edu"), email=row[FIELD_ORDERING.index("Email Address")].value.lower().replace("hmc.edu", "g.hmc.edu"), password=temp_password, ) new_user.first_name = first_name new_user.last_name = last_name new_user.save() studentid = (int(row[FIELD_ORDERING.index("ID")].value),) studentid = None new_student, _ = Student.objects.get_or_create( user=new_user, class_of=gradyear, at=hmc, studentid=studentid ) new_student.middle_name = (middle_name,) new_student.temp_pass = (temp_password,) new_student.save() dormname = row[FIELD_ORDERING.index("Dorm")].value.split(" ") if dormname[0] != "": if dormname[0] == "CGU": dormname = " ".join(dormname) else: dormname = dormname[0] dorm = Dorm.objects.get(name__startswith=dormname) room, _ = DormRoom.objects.get_or_create(dorm=dorm, number=row[FIELD_ORDERING.index("Room")].value) ur, _ = UserRoom.objects.get_or_create(user=new_user, room=room) ur.semesters.add(Semester.objects.get(half=kwargs["semester"], year=int(kwargs["year"])))
def post(self, *args, **kwargs): # block POSTs from most people. userrole = ASHMCAppointment.get_current_highest(self.request.user) minimum_role = ASHMCRole.objects.get(title=ASHMCRole.COUNCIL_ROLES[2]) if userrole < minimum_role: if "Class President" not in userrole.title: raise PermissionDenied() form_class = self.get_form_class() # This setting to None is a hack to make the get_form call work. self.object = None form = self.get_form(form_class) if not form.is_valid(): return self.form_invalid(form) print form.cleaned_data # The measure itself is valid; create it. new_measure = Measure.objects.create( name=form.cleaned_data['name'], vote_start=form.cleaned_data['vote_start'], vote_end=form.cleaned_data['vote_end'], summary=form.cleaned_data['summary'], quorum=form.cleaned_data['quorum'], is_open=form.cleaned_data['is_open'], ) logger.info("Created measure %d", new_measure.id) # This doesn't currently allow banned_accounts to be added. You need # use the regular admin for that. if isinstance(self.request.user.highest_ashmc_role.cast(), DormPresident): # Dorm presidents can only send measures to their dorm. logger.debug("dorm president dorm restriction") real_role = self.request.user.highest_ashmc_role.cast() dorm_restrictions = [real_role.dorm] elif self.request.user.highest_ashmc_role > ASHMCRole.objects.get(title=ASHMCRole.COUNCIL_ROLES[3]): logger.debug("unrestricted dorm restriction") # VP and president can restrict dorm as they choose. dorm_restrictions = Dorm.objects.filter(pk__in=self.request.POST.getlist('dorms')) else: logger.debug("no dorm restriction allowed") dorm_restrictions = [] if self.request.user.highest_ashmc_role.title.endswith("Class President"): logger.debug("Enacting class-president restriction") # Year-based class presidents can only send measure to their constituencies. if self.request.user.highest_ashmc_role.title.startswith("Senior"): year_restrictions = [GradYear.senior_class()] elif self.request.user.highest_ashmc_role.title.startswith("Junior"): year_restrictions = [GradYear.senior_class() - 1] elif self.request.user.highest_ashmc_role.title.startswith("Sophomore"): year_restrictions = [GradYear.senior_class() - 2] else: year_restrictions = [GradYear.senior_class() - 3] else: year_restrictions = GradYear.objects.filter(pk__in=self.request.POST.getlist('gradyears')) # Update the Restrictions object for this new_measure. restrictions = new_measure.restrictions restrictions.gradyears.add(*[gy for gy in year_restrictions]) restrictions.dorms.add(*[d for d in dorm_restrictions]) # Now, ballot creation. # Ballots fields all look like r"(\d+)_.*". # There will always be at least one ballot; gather all the specified # attributes in a ballots_dict, to be used later to create the actual ballots # and candidates. ballots_dict = {} for key in self.request.POST: if not re.match(r"^\d+_", key): continue if self.request.POST[key] == "on": keyval = True else: keyval = self.request.POST[key] ballot_sep_index = key.index('_') ballot_num = int(key[:ballot_sep_index]) # create an empty dict with ballot num as key if it doesn't already exist. ballots_dict.setdefault(ballot_num, {}) key_rest = key[ballot_sep_index + 1:] if re.match(r"\d+_", key_rest): # this is a candidate field -- they will always start with # r"\d+_\d+_" ballots_dict[ballot_num].setdefault('candidates', {}) candidate_sep_index = key_rest.index('_') candidate_num = int(key_rest[:candidate_sep_index]) key_rest_rest = key_rest[candidate_sep_index + 1:] ballots_dict[ballot_num]['candidates'].setdefault(candidate_num, {}) ballots_dict[ballot_num]['candidates'][candidate_num][key_rest_rest] = keyval else: # this is a ballot field. ballots_dict[ballot_num][key_rest] = keyval for ballot_num in ballots_dict: ballot_dict = ballots_dict[ballot_num] # sanitize ballot info for key, val in ballot_dict.items(): if val == "": del ballot_dict[key] if "can_abstain" not in ballot_dict: ballot_dict["can_abstain"] = False candidate_info = ballot_dict.pop('candidates', {}) ballot = Ballot.objects.create(measure=new_measure, **ballot_dict) logger.info("M%d: created ballot %d", new_measure.id, ballot.id) for candidate_num in candidate_info.keys(): candidate_dict = candidate_info[candidate_num] is_person = candidate_dict.pop('is_person', False) if is_person: usernames = candidate_dict['title'].split(' ') try: # Only support username students = Student.objects.filter(user__username__in=usernames) # if there's any problems, give up and create a normal # candidate. if not students: logger.warn("Could not find usernames: {}".format(usernames)) raise Student.DoesNotExist("Could not find usernames: {}".format(usernames)) elif len(students) != len(usernames): logger.warn("Could not find all usernames: {} (found {})".format(usernames, students)) raise Student.DoesNotExist( "Could not find all usernames: {} (found {})".format(usernames, students) ) candidate = PersonCandidate.objects.create( ballot=ballot, **candidate_dict ) logger.info("M%dB%d: created person candidate for %s", new_measure.id, ballot.id, students) for student in students: CandidateUser.objects.create( user=student.user, person_candidate=candidate, ) except Student.DoesNotExist: logger.warn("M%dB%d: creating fallback candidate (instead of person candidate)", new_measure.id, ballot.id) candidate = Candidate.objects.create( ballot=ballot, **candidate_dict ) print 'new candy keys:', candidate_info.keys() else: candidate = Candidate.objects.create( ballot=ballot, **candidate_dict ) logger.info("M%dB%d: created candidate %d", new_measure.id, ballot.id, candidate.id) # Finally, take them to the measure list. return redirect('measure_list')