# -*- coding: utf-8 -*- from __future__ import print_function, unicode_literals import dateutil.parser import csv from os.path import dirname, join import re import string import codecs import requests from django.core.management.base import BaseCommand from candidates.utils import strip_accents from candidates.views.version_data import get_change_metadata from elections.models import Election UNKNOWN_PARTY_ID = 'unknown' USER_AGENT = ( 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 ' '(KHTML, like Gecko) Ubuntu Chromium/38.0.2125.111 ' 'Chrome/38.0.2125.111Safari/537.36' ) def get_post_data(api, election_id, province): from candidates.cache import get_post_cached from candidates.election_specific import AREA_DATA, AREA_POST_DATA ynr_election_data = Election.objects.get_by_slug(election_id) area_key = (ynr_election_data.area_types.first().name, ynr_election_data.area_generation) areas_by_name = AREA_DATA.areas_by_name[area_key] if province != 'Burkina Faso': province = strip_accents(province).upper() area = areas_by_name[province] post_id = AREA_POST_DATA.get_post_id( election_id, area['type'], area['id'] ) post_data = get_post_cached(api, post_id)['result'] return ynr_election_data, post_data def get_existing_popit_person(vi_person_id): from candidates.models import PopItPerson from candidates.popit import get_search_url # See if this person already exists by searching for the # ID they were imported with: query_format = \ 'identifiers.identifier:"{id}" AND ' + \ 'identifiers.scheme:"{scheme}"' search_url = get_search_url( 'persons', query_format.format( id=vi_person_id, scheme='import-id' ), embed='membership.organization' ) results = requests.get(search_url).json() total = results['total'] if total > 1: message = "Multiple matches for CI ID {0}" raise Exception(message.format(vi_person_id)) if total == 0: return None # Otherwise there was exactly one result: return PopItPerson.create_from_dict(results['result'][0]) def get_party_data(party_name): from candidates.popit import get_search_url # See if this person already exists by searching for the # ID they were imported with: party_name = party_name.replace('/', '') party_name = party_name.decode('utf-8') query_format = \ 'name:"{name}"' search_url = get_search_url( 'organizations', query_format.format( name=party_name ) ) print(party_name) results = requests.get(search_url).json() print(results) total = results['total'] if total > 1: message = "Multiple matches for party {0}" raise Exception(message.format(party_name)) if total == 0: return None # Otherwise there was exactly one result: return results['result'][0] """ These functions taken from the csv docs - https://docs.python.org/2/library/csv.html#examples""" def unicode_csv_reader(unicode_csv_data, dialect=csv.excel, **kwargs): # csv.py doesn't do Unicode; encode temporarily as UTF-8: csv_reader = csv.reader(utf_8_encoder(unicode_csv_data), dialect=dialect, **kwargs) for row in csv_reader: # decode UTF-8 back to Unicode, cell by cell: yield [cell.decode('utf-8') for cell in row] def utf_8_encoder(unicode_csv_data): for line in unicode_csv_data: yield line.encode('utf-8') class Command(BaseCommand): help = "Import inital candidate data" def handle(self, username=None, **options): from slumber.exceptions import HttpClientError from candidates.election_specific import PARTY_DATA, shorten_post_label from candidates.models import PopItPerson from candidates.popit import create_popit_api_object election_data = { 'prv-2015': 'listedescandidatsauxelectionslegislativeslisteprovincialeanptic.csv', 'nat-2015': 'listedescandidatsauxelectionslegislativesanptic.csv' } field_map = { 'prv-2015': { 'region': 1, 'party': 4, 'list_order': 5, 'first_name': 7, 'last_name': 6, 'gender': 8, 'birth_date': 9, 'party_short': 3 }, 'nat-2015': { 'region': 0, 'party': 2, 'list_order': 3, 'first_name': 5, 'last_name': 4, 'gender': 6, 'birth_date': 7, 'party_short': 2 } } api = create_popit_api_object() party_id_missing = {} party_name_to_id = {} for party_id, party_name in PARTY_DATA.party_id_to_name.items(): party_name_to_id[party_name] = party_id for election_id, filename in election_data.items(): csv_filename = join( dirname(__file__), '..', '..', 'data', filename ) fields = field_map[election_id] with codecs.open(csv_filename, 'r', encoding='windows-1252') as f: initial = True for candidate in unicode_csv_reader(f): # skip header line if initial: initial = False continue region = candidate[fields['region']] party = candidate[fields['party']] party_list_order = candidate[fields['list_order']] first_name = string.capwords(candidate[fields['first_name']]) last_name = string.capwords(candidate[fields['last_name']]) gender = candidate[fields['gender']] birth_date = None if candidate[fields['birth_date']] is not None: birth_date = str(dateutil.parser.parse( candidate[fields['birth_date']], dayfirst=True ).date()) name = first_name + ' ' + last_name id = '-'.join([ re.sub('[^\w]*', '', re.sub(r' ', '-', strip_accents(name.lower()))), re.sub('[^\w]*', '', candidate[fields['party_short']].lower()), birth_date ]) # national candidate if region == 'PAYS': region = 'Burkina Faso' election_data, post_data = get_post_data( api, election_id, region ) # debug # tmp = '%s %s %s (%s) - %s (%s)' % ( id, first_name, last_name, party, region, post_data['label'] ) # print(tmp) person = get_existing_popit_person(id) if person: # print("Found an existing person:", person.get_absolute_url()) pass else: print("No existing person, creating a new one:", name) person = PopItPerson() person.set_identifier('import-id', id) person.family_name = last_name person.given_name = first_name person.name = name person.gender = gender if birth_date: person.birth_date = str(birth_date) else: person.birth_date = None standing_in_election = { 'post_id': post_data['id'], 'name': shorten_post_label(post_data['label']), 'party_list_position': party_list_order, } if 'area' in post_data: standing_in_election['mapit_url'] = post_data['area']['identifier'] person.standing_in = { election_data.slug: standing_in_election } change_metadata = get_change_metadata( None, 'Imported candidate from CSV', ) party_comp = re.sub(' +', ' ', party) party_id = UNKNOWN_PARTY_ID if party_comp in party_name_to_id.keys(): party_id = party_name_to_id[party_comp] party = party_comp else: party_id = party_name_to_id['Unknown Party'] party = 'Unknown Party' if party_id == UNKNOWN_PARTY_ID and party_comp not in party_id_missing.keys(): party_id_missing[party_comp] = 1 person.party_memberships = { election_data.slug: { 'id': party_id, 'name': party, 'imported_name': party_comp } } person.record_version(change_metadata) try: person.save_to_popit(api) except HttpClientError as hce: print("Got an HttpClientError:", hce.content) raise if len(party_id_missing) > 0: print("Unmatched party names:") for name in party_id_missing.keys(): print(name)