def import_maplight_from_json(request): load_from_url = False ballot_for_one_voter_array = [] if load_from_url: # Request json file from Maplight servers logger.debug("TO BE IMPLEMENTED: Load Maplight JSON from url") # request = requests.get(VOTER_INFO_URL, params={ # "key": GOOGLE_CIVIC_API_KEY, # This comes from an environment variable # "address": "254 Hartford Street San Francisco CA", # "electionId": "2000", # }) # structured_json = json.loads(request.text) else: # Load saved json from local file logger.debug("Loading Maplight sample JSON from local file") with open( MAPLIGHT_SAMPLE_BALLOT_JSON_FILE) as ballot_for_one_voter_json: ballot_for_one_voter_array = json.load(ballot_for_one_voter_json) # A MapLight ballot query is essentially an array of contests with the key as the contest_id if ballot_for_one_voter_array and len(ballot_for_one_voter_array): # Parse the JSON here. This JSON is a list of contests on the ballot for one voter. for contest_id in ballot_for_one_voter_array: # Get a description of the contest. Office? Measure? contest_overview_array = ballot_for_one_voter_array[contest_id] if contest_overview_array['type'] == "office": # Get a description of the office the candidates are competing for # contest_office_description_json = contest_overview_array['office'] # With the contest_id, we can look up who is running politicians_running_for_one_contest_array = [] if load_from_url: logger.debug( "TO BE IMPLEMENTED: Load MapLight JSON for a contest from URL" ) else: json_file_with_the_data_from_this_contest = MAPLIGHT_SAMPLE_CONTEST_JSON_FILE.format( contest_id=contest_id) try: with open(json_file_with_the_data_from_this_contest ) as json_data: politicians_running_for_one_contest_array = json.load( json_data) except Exception as e: logger.error("File {file_path} not found.".format( file_path=json_file_with_the_data_from_this_contest )) # Don't try to process the file if it doesn't exist, but go to the next entry continue import_maplight_contest_office_candidates_from_array( politicians_running_for_one_contest_array) # Also add measure return
def process_contest_referendum_from_structured_json( one_contest_referendum_structured_json, google_civic_election_id, local_ballot_order, save_to_db): """ "referendumTitle": "Proposition 45", "referendumSubtitle": "Healthcare Insurance. Rate Changes. Initiative Statute.", "referendumUrl": "http://vig.cdn.sos.ca.gov/2014/general/en/pdf/proposition-45-title-summary-analysis.pdf", "district" <= this is an array """ logger.debug("Referendum contest_type") referendum_title = one_contest_referendum_structured_json['referendumTitle'] referendum_subtitle = one_contest_referendum_structured_json['referendumSubtitle'] referendum_url = one_contest_referendum_structured_json['referendumUrl'] # These following fields exist for both candidates and referendum results = process_contest_common_fields_from_structured_json(one_contest_referendum_structured_json) ballot_placement = results['ballot_placement'] # A number specifying the position of this contest # on the voter's ballot. primary_party = results['primary_party'] # If this is a partisan election, the name of the party it is for. district_name = results['district_name'] # The name of the district. district_scope = results['district_scope'] # The geographic scope of this district. If unspecified the # district's geography is not known. One of: national, statewide, congressional, stateUpper, stateLower, # countywide, judicial, schoolBoard, cityWide, township, countyCouncil, cityCouncil, ward, special district_ocd_id = results['district_ocd_id'] electorate_specifications = results['electorate_specifications'] # A description of any additional # eligibility requirements for voting in this contest. special = results['special'] # "Yes" or "No" depending on whether this a contest being held # outside the normal election cycle. if save_to_db: if referendum_title and referendum_subtitle and district_name and district_scope and district_ocd_id \ and google_civic_election_id: try: query1 = GoogleCivicContestReferendum.objects.all() query1 = query1.filter(referendum_title__exact=referendum_title) query1 = query1.filter(google_civic_election_id__exact=google_civic_election_id) query1 = query1.filter(district_scope__exact=district_scope) # Was at least one existing entry found based on the above criteria? if len(query1): google_civic_contest_referendum = query1[0] # If no entries found previously, create a new entry else: google_civic_contest_referendum = \ GoogleCivicContestReferendum.objects.create(referendum_title=referendum_title, referendum_subtitle=referendum_subtitle, google_civic_election_id=google_civic_election_id, referendum_url=referendum_url, ballot_placement=ballot_placement, primary_party=primary_party, district_name=district_name, district_scope=district_scope, district_ocd_id=district_ocd_id, electorate_specifications=electorate_specifications, special=special, ) # Save information about this contest item on the voter's ballot from: ballot_placement except Exception as e: handle_record_not_found_exception(e, logger=logger) return
def process_contest_office_from_structured_json( one_contest_office_structured_json, google_civic_election_id, local_ballot_order, save_to_db): voter_id = 1 # TODO Temp logger.debug("General contest_type") office = one_contest_office_structured_json['office'] # The number of candidates that a voter may vote for in this contest. if 'numberVotingFor' in one_contest_office_structured_json: number_voting_for = one_contest_office_structured_json['numberVotingFor'] else: number_voting_for = 1 # The number of candidates that will be elected to office in this contest. if 'numberElected' in one_contest_office_structured_json: number_elected = one_contest_office_structured_json['numberElected'] else: number_elected = 1 results = process_contest_common_fields_from_structured_json(one_contest_office_structured_json) ballot_placement = results['ballot_placement'] # A number specifying the position of this contest # on the voter's ballot. primary_party = results['primary_party'] # If this is a partisan election, the name of the party it is for. district_name = results['district_name'] # The name of the district. district_scope = results['district_scope'] # The geographic scope of this district. If unspecified the # district's geography is not known. One of: national, statewide, congressional, stateUpper, stateLower, # countywide, judicial, schoolBoard, cityWide, township, countyCouncil, cityCouncil, ward, special district_ocd_id = results['district_ocd_id'] electorate_specifications = results['electorate_specifications'] # A description of any additional # eligibility requirements for voting in this contest. special = results['special'] # "Yes" or "No" depending on whether this a contest being held # outside the normal election cycle. # We want to convert this from an array to three fields for the same table # levels: string, A list of office levels to filter by. Only offices that serve at least one of these levels # will be returned. Divisions that don't contain a matching office will not be returned. (repeated) # Allowed values # administrativeArea1 - # administrativeArea2 - # country - # international - # locality - # regional - # special - # subLocality1 - # subLocality2 - # The levels of government of the office for this contest. There may be more than one in cases where a # jurisdiction effectively acts at two different levels of government; for example, the mayor of the # District of Columbia acts at "locality" level, but also effectively at both "administrative-area-2" # and "administrative-area-1". level_structured_json = one_contest_office_structured_json['level'] contest_level = [] for one_level in level_structured_json: contest_level.append(one_level) if 0 in contest_level: contest_level0 = contest_level[0] else: contest_level0 = '' if 1 in contest_level: contest_level1 = contest_level[1] else: contest_level1 = '' if 2 in contest_level: contest_level2 = contest_level[2] else: contest_level2 = '' # roles: string, A list of office roles to filter by. Only offices fulfilling one of these roles will be returned. # Divisions that don't contain a matching office will not be returned. (repeated) # Allowed values # deputyHeadOfGovernment - # executiveCouncil - # governmentOfficer - # headOfGovernment - # headOfState - # highestCourtJudge - # judge - # legislatorLowerBody - # legislatorUpperBody - # schoolBoard - # specialPurposeOfficer - roles_structured_json = one_contest_office_structured_json['roles'] # for one_role in roles_structured_json: # Figure out how we are going to use level info candidates = one_contest_office_structured_json['candidates'] internal_contest_office_id = 0 # Set to 0 in case a new one is not created # Note that all of the information saved here is independent of a particular voter if save_to_db: if office and district_name and district_scope and district_ocd_id and google_civic_election_id: try: # Try to find earlier version based on name of the office google_civic_election_id query1 = GoogleCivicContestOffice.objects.all() query1 = query1.filter(google_civic_election_id__exact=google_civic_election_id) query1 = query1.filter(district_scope__exact=district_scope) query1 = query1.filter(office__exact=office) # Was at least one existing entry found based on the above criteria? if len(query1): google_civic_contest_office = query1[0] # If no entries found previously, create a new entry else: google_civic_contest_office = \ GoogleCivicContestOffice.objects.create(office=office, google_civic_election_id=google_civic_election_id, number_voting_for=number_voting_for, number_elected=number_elected, contest_level0=contest_level0, contest_level1=contest_level1, contest_level2=contest_level2, ballot_placement=ballot_placement, primary_party=primary_party, district_name=district_name, district_scope=district_scope, district_ocd_id=district_ocd_id, electorate_specifications=electorate_specifications, special=special, ) # The internal id is needed since there isn't a ContestOffice google identifier internal_contest_office_id = google_civic_contest_office.id except Exception as e: handle_record_not_found_exception(e, logger=logger) if value_exists(voter_id) and value_exists(google_civic_election_id) and value_exists(district_ocd_id): google_civic_ballot_item_manager = GoogleCivicBallotItemManager() google_civic_ballot_item_manager.save_ballot_item_for_voter( voter_id, google_civic_election_id, district_ocd_id, ballot_placement, local_ballot_order) process_candidates_from_structured_json( candidates, google_civic_election_id, internal_contest_office_id, save_to_db) return
def process_contest_office_from_structured_json( one_contest_office_structured_json, google_civic_election_id, ocd_division_id, local_ballot_order, state_code, voter_id): logger.debug("General contest_type") # Protect against the case where this is NOT an office if 'candidates' not in one_contest_office_structured_json: is_not_office = True else: is_not_office = False if is_not_office: update_or_create_contest_office_results = { 'success': False, 'saved': 0, 'updated': 0, 'not_processed': 1, } return update_or_create_contest_office_results office_name = one_contest_office_structured_json['office'] # The number of candidates that a voter may vote for in this contest. if 'numberVotingFor' in one_contest_office_structured_json: number_voting_for = one_contest_office_structured_json['numberVotingFor'] else: number_voting_for = 1 # The number of candidates that will be elected to office in this contest. if 'numberElected' in one_contest_office_structured_json: number_elected = one_contest_office_structured_json['numberElected'] else: number_elected = 1 # These are several fields that are shared in common between offices and measures results = process_contest_common_fields_from_structured_json(one_contest_office_structured_json) # ballot_placement: A number specifying the position of this contest on the voter's ballot. google_ballot_placement = results['ballot_placement'] primary_party = results['primary_party'] # If this is a partisan election, the name of the party it is for. # district_scope: The geographic scope of this district. If unspecified the # district's geography is not known. One of: national, statewide, congressional, stateUpper, stateLower, # countywide, judicial, schoolBoard, cityWide, township, countyCouncil, cityCouncil, ward, special district_scope = results['district_scope'] district_id = results['district_id'] district_name = results['district_name'] # The name of the district. # electorate_specifications: A description of any additional eligibility requirements for voting in this contest. electorate_specifications = results['electorate_specifications'] # special: "Yes" or "No" depending on whether this a contest being held outside the normal election cycle. special = results['special'] # We want to convert this from an array to three fields for the same table # levels: string, A list of office levels to filter by. Only offices that serve at least one of these levels # will be returned. Divisions that don't contain a matching office will not be returned. (repeated) # Allowed values # administrativeArea1 - # administrativeArea2 - # country - # international - # locality - # regional - # special - # subLocality1 - # subLocality2 - # The levels of government of the office for this contest. There may be more than one in cases where a # jurisdiction effectively acts at two different levels of government; for example, the mayor of the # District of Columbia acts at "locality" level, but also effectively at both "administrative-area-2" # and "administrative-area-1". level_structured_json = \ one_contest_office_structured_json['level'] if 'level' in one_contest_office_structured_json else '' contest_level = [] for one_level in level_structured_json: contest_level.append(one_level) if 0 in contest_level: contest_level0 = contest_level[0] else: contest_level0 = '' if 1 in contest_level: contest_level1 = contest_level[1] else: contest_level1 = '' if 2 in contest_level: contest_level2 = contest_level[2] else: contest_level2 = '' # roles: string, A list of office roles to filter by. Only offices fulfilling one of these roles will be returned. # Divisions that don't contain a matching office will not be returned. (repeated) # Allowed values # deputyHeadOfGovernment - # executiveCouncil - # governmentOfficer - # headOfGovernment - # headOfState - # highestCourtJudge - # judge - # legislatorLowerBody - # legislatorUpperBody - # schoolBoard - # specialPurposeOfficer - # roles_structured_json = \ # one_contest_office_structured_json['roles'] if 'roles' in one_contest_office_structured_json else '' # for one_role in roles_structured_json: # Figure out how we are going to use level info candidates_structured_json = \ one_contest_office_structured_json['candidates'] if 'candidates' in one_contest_office_structured_json else '' we_vote_id = '' # Note that all of the information saved here is independent of a particular voter if google_civic_election_id and (district_id or district_name) and office_name: updated_contest_office_values = { # Values we search against 'google_civic_election_id': google_civic_election_id, 'state_code': state_code.lower(), # Not required for cases of federal offices 'district_id': district_id, 'district_name': district_name, 'office_name': office_name, # The rest of the values 'ocd_division_id': ocd_division_id, 'number_voting_for': number_voting_for, 'number_elected': number_elected, 'contest_level0': contest_level0, 'contest_level1': contest_level1, 'contest_level2': contest_level2, 'primary_party': primary_party, 'district_scope': district_scope, 'electorate_specifications': electorate_specifications, 'special': special, } contest_office_manager = ContestOfficeManager() update_or_create_contest_office_results = contest_office_manager.update_or_create_contest_office( we_vote_id, google_civic_election_id, district_id, district_name, office_name, state_code, updated_contest_office_values) else: update_or_create_contest_office_results = { 'success': False, 'saved': 0, 'updated': 0, 'not_processed': 1, } if update_or_create_contest_office_results['success']: contest_office = update_or_create_contest_office_results['contest_office'] contest_office_id = contest_office.id contest_office_we_vote_id = contest_office.we_vote_id ballot_item_display_name = contest_office.office_name else: contest_office_id = 0 contest_office_we_vote_id = '' ballot_item_display_name = '' # If a voter_id was passed in, save an entry for this office for the voter's ballot if positive_value_exists(voter_id) and positive_value_exists(google_civic_election_id) \ and positive_value_exists(contest_office_id): ballot_item_manager = BallotItemManager() ballot_item_manager.update_or_create_ballot_item_for_voter( voter_id, google_civic_election_id, google_ballot_placement, ballot_item_display_name, local_ballot_order, contest_office_id, contest_office_we_vote_id) # We leave off these and rely on default empty values: contest_measure_id, contest_measure_we_vote_id # Note: We do not need to connect the candidates with the voter here for a ballot item process_candidates_from_structured_json( candidates_structured_json, google_civic_election_id, ocd_division_id, state_code, contest_office_id, contest_office_we_vote_id) return update_or_create_contest_office_results
def process_contest_referendum_from_structured_json( one_contest_referendum_structured_json, google_civic_election_id, local_ballot_order, save_to_db): """ "referendumTitle": "Proposition 45", "referendumSubtitle": "Healthcare Insurance. Rate Changes. Initiative Statute.", "referendumUrl": "http://vig.cdn.sos.ca.gov/2014/general/en/pdf/proposition-45-title-summary-analysis.pdf", "district" <= this is an array """ logger.debug("Referendum contest_type") referendum_title = one_contest_referendum_structured_json[ 'referendumTitle'] referendum_subtitle = one_contest_referendum_structured_json[ 'referendumSubtitle'] referendum_url = one_contest_referendum_structured_json['referendumUrl'] # These following fields exist for both candidates and referendum results = process_contest_common_fields_from_structured_json( one_contest_referendum_structured_json) ballot_placement = results[ 'ballot_placement'] # A number specifying the position of this contest # on the voter's ballot. primary_party = results[ 'primary_party'] # If this is a partisan election, the name of the party it is for. district_name = results['district_name'] # The name of the district. district_scope = results[ 'district_scope'] # The geographic scope of this district. If unspecified the # district's geography is not known. One of: national, statewide, congressional, stateUpper, stateLower, # countywide, judicial, schoolBoard, cityWide, township, countyCouncil, cityCouncil, ward, special district_ocd_id = results['district_ocd_id'] electorate_specifications = results[ 'electorate_specifications'] # A description of any additional # eligibility requirements for voting in this contest. special = results[ 'special'] # "Yes" or "No" depending on whether this a contest being held # outside the normal election cycle. if save_to_db: if referendum_title and referendum_subtitle and district_name and district_scope and district_ocd_id \ and google_civic_election_id: try: query1 = GoogleCivicContestReferendum.objects.all() query1 = query1.filter( referendum_title__exact=referendum_title) query1 = query1.filter( google_civic_election_id__exact=google_civic_election_id) query1 = query1.filter(district_scope__exact=district_scope) # Was at least one existing entry found based on the above criteria? if len(query1): google_civic_contest_referendum = query1[0] # If no entries found previously, create a new entry else: google_civic_contest_referendum = \ GoogleCivicContestReferendum.objects.create(referendum_title=referendum_title, referendum_subtitle=referendum_subtitle, google_civic_election_id=google_civic_election_id, referendum_url=referendum_url, ballot_placement=ballot_placement, primary_party=primary_party, district_name=district_name, district_scope=district_scope, district_ocd_id=district_ocd_id, electorate_specifications=electorate_specifications, special=special, ) # Save information about this contest item on the voter's ballot from: ballot_placement except Exception as e: handle_record_not_found_exception(e, logger=logger) return
def process_contest_office_from_structured_json( one_contest_office_structured_json, google_civic_election_id, local_ballot_order, save_to_db): voter_id = 1 # TODO Temp logger.debug("General contest_type") office = one_contest_office_structured_json['office'] # The number of candidates that a voter may vote for in this contest. if 'numberVotingFor' in one_contest_office_structured_json: number_voting_for = one_contest_office_structured_json[ 'numberVotingFor'] else: number_voting_for = 1 # The number of candidates that will be elected to office in this contest. if 'numberElected' in one_contest_office_structured_json: number_elected = one_contest_office_structured_json['numberElected'] else: number_elected = 1 results = process_contest_common_fields_from_structured_json( one_contest_office_structured_json) ballot_placement = results[ 'ballot_placement'] # A number specifying the position of this contest # on the voter's ballot. primary_party = results[ 'primary_party'] # If this is a partisan election, the name of the party it is for. district_name = results['district_name'] # The name of the district. district_scope = results[ 'district_scope'] # The geographic scope of this district. If unspecified the # district's geography is not known. One of: national, statewide, congressional, stateUpper, stateLower, # countywide, judicial, schoolBoard, cityWide, township, countyCouncil, cityCouncil, ward, special district_ocd_id = results['district_ocd_id'] electorate_specifications = results[ 'electorate_specifications'] # A description of any additional # eligibility requirements for voting in this contest. special = results[ 'special'] # "Yes" or "No" depending on whether this a contest being held # outside the normal election cycle. # We want to convert this from an array to three fields for the same table # levels: string, A list of office levels to filter by. Only offices that serve at least one of these levels # will be returned. Divisions that don't contain a matching office will not be returned. (repeated) # Allowed values # administrativeArea1 - # administrativeArea2 - # country - # international - # locality - # regional - # special - # subLocality1 - # subLocality2 - # The levels of government of the office for this contest. There may be more than one in cases where a # jurisdiction effectively acts at two different levels of government; for example, the mayor of the # District of Columbia acts at "locality" level, but also effectively at both "administrative-area-2" # and "administrative-area-1". level_structured_json = one_contest_office_structured_json['level'] contest_level = [] for one_level in level_structured_json: contest_level.append(one_level) if 0 in contest_level: contest_level0 = contest_level[0] else: contest_level0 = '' if 1 in contest_level: contest_level1 = contest_level[1] else: contest_level1 = '' if 2 in contest_level: contest_level2 = contest_level[2] else: contest_level2 = '' # roles: string, A list of office roles to filter by. Only offices fulfilling one of these roles will be returned. # Divisions that don't contain a matching office will not be returned. (repeated) # Allowed values # deputyHeadOfGovernment - # executiveCouncil - # governmentOfficer - # headOfGovernment - # headOfState - # highestCourtJudge - # judge - # legislatorLowerBody - # legislatorUpperBody - # schoolBoard - # specialPurposeOfficer - roles_structured_json = one_contest_office_structured_json['roles'] # for one_role in roles_structured_json: # Figure out how we are going to use level info candidates = one_contest_office_structured_json['candidates'] internal_contest_office_id = 0 # Set to 0 in case a new one is not created # Note that all of the information saved here is independent of a particular voter if save_to_db: if office and district_name and district_scope and district_ocd_id and google_civic_election_id: try: # Try to find earlier version based on name of the office google_civic_election_id query1 = GoogleCivicContestOffice.objects.all() query1 = query1.filter( google_civic_election_id__exact=google_civic_election_id) query1 = query1.filter(district_scope__exact=district_scope) query1 = query1.filter(office__exact=office) # Was at least one existing entry found based on the above criteria? if len(query1): google_civic_contest_office = query1[0] # If no entries found previously, create a new entry else: google_civic_contest_office = \ GoogleCivicContestOffice.objects.create(office=office, google_civic_election_id=google_civic_election_id, number_voting_for=number_voting_for, number_elected=number_elected, contest_level0=contest_level0, contest_level1=contest_level1, contest_level2=contest_level2, ballot_placement=ballot_placement, primary_party=primary_party, district_name=district_name, district_scope=district_scope, district_ocd_id=district_ocd_id, electorate_specifications=electorate_specifications, special=special, ) # The internal id is needed since there isn't a ContestOffice google identifier internal_contest_office_id = google_civic_contest_office.id except Exception as e: handle_record_not_found_exception(e, logger=logger) if value_exists(voter_id) and value_exists( google_civic_election_id) and value_exists(district_ocd_id): google_civic_ballot_item_manager = GoogleCivicBallotItemManager() google_civic_ballot_item_manager.save_ballot_item_for_voter( voter_id, google_civic_election_id, district_ocd_id, ballot_placement, local_ballot_order) process_candidates_from_structured_json(candidates, google_civic_election_id, internal_contest_office_id, save_to_db) return