def test_location_resolving(self): # test basic address lookup -- ensure zip and geocoding info is filled in # https://maps.googleapis.com/maps/api/geocode/json?address=3411+Blvd+of+the+Allies®ion=US&sensor=false resolved = pl_outsourcing.resolve_location(Location(address='3411 Blvd of the Allies')) self.assertEquals(resolved.address,'3411 Boulevard of the Allies') self.assertEquals(resolved.postcode,'15213') self.assertEquals(resolved.town,'Pittsburgh') self.assertEquals(resolved.state,'PA') self.assertEquals(resolved.country,'US') self.assertAlmostEquals(resolved.latitude,40.435938,3) # assert equals up to 2 places self.assertAlmostEquals(resolved.longitude,-79.958309,3) # test zip codes properly bias searches -- if these fail, make sure the geocoding info # at the following links matches the expected values below: # https://maps.googleapis.com/maps/api/geocode/json?address=800+penn+ave%2C+15222®ion=US&sensor=false # https://maps.googleapis.com/maps/api/geocode/json?address=800+penn+ave%2C+15221®ion=US&sensor=false resolved = pl_outsourcing.resolve_location(Location(address='800 penn ave',postcode='15222')) self.assertAlmostEquals(resolved.latitude,40.443290,places=4) # assert equals up to 2 places self.assertAlmostEquals(resolved.longitude,-79.999092,places=2) resolved = pl_outsourcing.resolve_location(Location(address='800 penn ave',postcode='15221')) self.assertAlmostEquals(resolved.latitude,40.442470,4) # assert equals up to 2 places self.assertAlmostEquals(resolved.longitude,-79.881871,2) # tests that geocoding info properly biases searches # expected results are based on the following geocoding API calls: # http://maps.googleapis.com/maps/api/geocode/json?region=US&sensor=false&bounds=40.438000%2C-80.005000%7C40.448000%2C-79.995000&address=800+penn+ave # http://maps.googleapis.com/maps/api/geocode/json?region=US&sensor=false&bounds=40.437000%2C-79.905000%7C40.447000%2C-79.895000&address=800+penn+ave resolved = pl_outsourcing.resolve_location(Location(address='800 penn ave',latitude=40.443,longitude=-80)) self.assertEquals(resolved.postcode,'15222') resolved = pl_outsourcing.resolve_location(Location(address='800 penn ave',latitude=40.442,longitude=-79.9)) self.assertEquals(resolved.postcode,'15221') # bad address unresolved = pl_outsourcing.resolve_location(Location(address='fakey fake double false address')) self.assertIsNone(unresolved)
def test_location_resolving(self): # test basic address lookup -- ensure zip and geocoding info is filled in # https://maps.googleapis.com/maps/api/geocode/json?address=3411+Blvd+of+the+Allies®ion=US&sensor=false resolved = pl_outsourcing.resolve_location( Location(address='3411 Blvd of the Allies')) self.assertEquals(resolved.address, '3411 Boulevard of the Allies') self.assertEquals(resolved.postcode, '15213') self.assertEquals(resolved.town, 'Pittsburgh') self.assertEquals(resolved.state, 'PA') self.assertEquals(resolved.country, 'US') self.assertAlmostEquals(resolved.latitude, 40.435938, 3) # assert equals up to 2 places self.assertAlmostEquals(resolved.longitude, -79.958309, 3) # test zip codes properly bias searches -- if these fail, make sure the geocoding info # at the following links matches the expected values below: # https://maps.googleapis.com/maps/api/geocode/json?address=800+penn+ave%2C+15222®ion=US&sensor=false # https://maps.googleapis.com/maps/api/geocode/json?address=800+penn+ave%2C+15221®ion=US&sensor=false resolved = pl_outsourcing.resolve_location( Location(address='800 penn ave', postcode='15222')) self.assertAlmostEquals(resolved.latitude, 40.443290, places=4) # assert equals up to 2 places self.assertAlmostEquals(resolved.longitude, -79.999092, places=2) resolved = pl_outsourcing.resolve_location( Location(address='800 penn ave', postcode='15221')) self.assertAlmostEquals(resolved.latitude, 40.442470, 4) # assert equals up to 2 places self.assertAlmostEquals(resolved.longitude, -79.881871, 2) # tests that geocoding info properly biases searches # expected results are based on the following geocoding API calls: # http://maps.googleapis.com/maps/api/geocode/json?region=US&sensor=false&bounds=40.438000%2C-80.005000%7C40.448000%2C-79.995000&address=800+penn+ave # http://maps.googleapis.com/maps/api/geocode/json?region=US&sensor=false&bounds=40.437000%2C-79.905000%7C40.447000%2C-79.895000&address=800+penn+ave resolved = pl_outsourcing.resolve_location( Location(address='800 penn ave', latitude=40.443, longitude=-80)) self.assertEquals(resolved.postcode, '15222') resolved = pl_outsourcing.resolve_location( Location(address='800 penn ave', latitude=40.442, longitude=-79.9)) self.assertEquals(resolved.postcode, '15221') # bad address unresolved = pl_outsourcing.resolve_location( Location(address='fakey fake double false address')) self.assertIsNone(unresolved)
def store_fbpage_place(page_info, create_owner=True): ''' Takes a dict of properties retreived from a Facebook Graph API call for a page and stores a Place from the information. The following fields in the dict are used: - id (required) - type (required with value 'page' or a TypeError will be thrown) - location (required or TypeError will be thrown) - description - url - phone - hours - picture No new Place will be returned if either an identical one already exists in the db, or an ExternalPlaceSource already exists for the given Facebook id. An INFO message is logged to note the attempt to store an existing page as a Place. If create_owner is True a new Organization will be created from the same page information if one does not already exist. ''' pid = page_info['id'] try: place = ExternalPlaceSource.objects.get(service='fb', uid=pid).place outsourcing_log.info('Existing fb page Place found for fbid %s' % unicode(pid)) return place except ExternalPlaceSource.DoesNotExist: pass if page_info.get('type') != 'page': raise TypeError("Cannot store object without 'page' type as a Place.") elif 'location' not in page_info: raise TypeError("Cannot store object without location key as a Place.") pname = page_info['name'].strip() ### Figure out the new Place's location field fbloc = page_info['location'] if 'id' in fbloc: # TODO: need to ensure fbloc_to_loc can handle ids in location if this ever happens outsourcing_log.info('Facebook page %s has id in location (%s)' % (pid, fbloc['id'])) location = fbloc_to_loc(fbloc) # if there's no address or geocoding, we'll need to talk to outside services if not location.address: seed_place = Place(name=pname, location=location) resolved_place = resolve_place(seed_place) if resolved_place: location = resolved_place.location # really want geolocation, go to Google Geocoding for it if we need it if location.longitude is None or location.latitude is None: seed_loc = copy.deepcopy(location) resolved_location = resolve_location(seed_loc, allow_numberless=False) if resolved_location: location = resolved_location # if there's no specific address information, make the error radius around the # lat/lng super tight. Don't want to create whirlpools. cl_opts = dict(lat_error=1e-5, lng_error=1e-5) if not location.address else {} location, created = Location.close_manager.get_close_or_create( address=location.address, postcode=location.postcode, town=location.town, state=location.state, country=location.country, neighborhood=location.neighborhood, latitude=location.latitude, longitude=location.longitude, _close_options=cl_opts) if created: outsourcing_log.debug('Saved new location "%s"' % location.full_string) else: outsourcing_log.debug('Retrieved existing location "%s"' % location.full_string) try: owner = FacebookOrgRecord.objects.get(fb_id=pid).organization except FacebookOrgRecord.DoesNotExist: if create_owner: outsourcing_log.info( 'Creating new Organization as byproduct of creating Place from Facebook page %s' % unicode(pid)) owner = store_fbpage_organization(page_info) else: owner = None place, created = Place.objects.get_or_create(name=pname[:200], description=page_info.get( 'description', '').strip(), location=location, owner=owner) # add place meta info that exists _store_fbpage_placemeta(page_info, place) # create a new link to an external id ExternalPlaceSource.objects.create(service='fb', uid=pid, place=place) return place
def run(): in_filename = os.path.join(os.path.dirname(__file__), 'obid.csv') #clear all tables Location.objects.all().delete() PlaceMeta.objects.all().delete() Place.objects.all().delete() Organization.objects.all().delete() ExternalPlaceSource.objects.all().delete() FacebookPage.objects.all().delete() FacebookOrgRecord.objects.all().delete() gplaces_category_map = load_category_map('google_places') gp_hits, gp_misses = 0, 0 rows = OBIDRow.rows_from_csv(in_filename) # cycle through each row with a facebook reference and store a reference page_mgr = PageImportManager() fb_rows = [row for row in rows if row.fb_id] for row, info in zip( fb_rows, page_mgr.pull_page_info([row.fb_id for row in fb_rows])): if isinstance(info, dict): info.pop('metadata', None) # don't need to store metadata if it exists FacebookPage.objects.get_or_create( fb_id=info['id'], defaults=dict(pageinfo_json=json.dumps(info))) row.fb_id = info['id'] # ensure a numeric id else: print 'ERROR: Pulling fb page %s resulted in the following exception: "%s"' % ( str(row.fb_id), str(info)) row.fb_id = '' # cycle through all rows and store everything for i, row in enumerate(rows): if not row.place: print 'ERROR: no place for entry %d' % i # resolve the location location = resolve_location( Location(address=row.address, postcode='15213')) if location: # hack to get around Google Geocoding appending the unviersity onto all addresses if ( location.address.startswith('University') and not row.address.lower().startswith('univ') ) or \ ( location.address.startswith('Carnegie Mellon') and row.address.lower().startswith('carnegie mellon') ): location.address = ','.join(location.address.split(',')[1:]) try: # if exact match exists, use it instead of the newly found one location = Location.objects.get(address=location.address, postcode=location.postcode) except Location.DoesNotExist: location.save() else: print 'WARNING: Geocoding failed for entry %d ("%s")' % (i, row.place) diff_org = row.org != row.place org, place = None, None # import org # if the row has a fb id, we'll try to import the Org from Facebook # only import Org from Facebook if it's the same as the Place (fb id relates to place only) if row.fb_id and not diff_org: try: org = FacebookOrgRecord.objects.get(fb_id=row.fb_id) except FacebookOrgRecord.DoesNotExist: report = page_mgr.import_org(row.fb_id) if report.model_instance: org = report.model_instance else: print 'WARNING: Organization FB import failed for entry %d (fbid %s)' % ( i, str(row.fb_id)) if not org: org, created = Organization.objects.get_or_create(name=row.org) # import place if row.fb_id: try: place = ExternalPlaceSource.facebook.get(uid=row.fb_id) except ExternalPlaceSource.DoesNotExist: report = page_mgr.import_place(row.fb_id, import_owners=False) if report.model_instance: place = report.model_instance if not place.owner: # no owner is created automatically, so set it if not created place.owner = org place.save() else: print 'WARNING: Place FB import failed for entry %d (fbid %s)' % ( i, str(row.fb_id)) if not place: place, created = Place.objects.get_or_create(name=row.place, location=location, owner=org) if row.url: PlaceMeta.objects.create(place=place, meta_key='url', meta_value=row.url) if not diff_org: # also save the url as the org's url if they're the same org.url = row.url org.save() if row.phone: PlaceMeta.objects.create(place=place, meta_key='phone', meta_value=row.phone) print 'Imported %s' % row.place try: print ' (linked to FB page %s)' % ExternalPlaceSource.facebook.get( place=place).uid except ExternalPlaceSource.DoesNotExist: pass # store tags from Google Place lookup if location and \ location.latitude is not None and location.longitude is not None: coords = (location.latitude, location.longitude) radius = 1000 else: coords = (40.4425, -79.9575) radius = 5000 response = gplaces_client.search_request(coords, radius, keyword=row.place) if len(response) > 0 and 'reference' in response[0]: details = gplaces_client.details_request(response[0]['reference']) all_tags = set() for typ in details.get('types', []): if typ in gplaces_category_map: all_tags.update(gplaces_category_map[typ]) else: print 'WARNING: Unknown Google Places type: "%s"' % typ if len(all_tags) > 0: print ' Tags:', for t in all_tags: print '%s,' % t, print gp_hits += 1 else: print ' WARNING: Failure querying Google Places for "%s" within %dm of (%f,%f)' % ( row.place, radius, coords[0], coords[1]) gp_misses += 1 print gp_hits, gp_misses
def run(): in_filename = os.path.join(os.path.dirname(__file__),'obid.csv') #clear all tables Location.objects.all().delete() PlaceMeta.objects.all().delete() Place.objects.all().delete() Organization.objects.all().delete() ExternalPlaceSource.objects.all().delete() FacebookPage.objects.all().delete() FacebookOrgRecord.objects.all().delete() gplaces_category_map = load_category_map('google_places') gp_hits, gp_misses = 0,0 rows = OBIDRow.rows_from_csv(in_filename) # cycle through each row with a facebook reference and store a reference page_mgr = PageImportManager() fb_rows = [row for row in rows if row.fb_id] for row,info in zip(fb_rows,page_mgr.pull_page_info([row.fb_id for row in fb_rows])): if isinstance(info,dict): info.pop('metadata',None) # don't need to store metadata if it exists FacebookPage.objects.get_or_create(fb_id=info['id'], defaults=dict(pageinfo_json=json.dumps(info))) row.fb_id = info['id'] # ensure a numeric id else: print 'ERROR: Pulling fb page %s resulted in the following exception: "%s"' % (str(row.fb_id),str(info)) row.fb_id = '' # cycle through all rows and store everything for i,row in enumerate(rows): if not row.place: print 'ERROR: no place for entry %d' % i # resolve the location location = resolve_location(Location(address=row.address,postcode='15213')) if location: # hack to get around Google Geocoding appending the unviersity onto all addresses if ( location.address.startswith('University') and not row.address.lower().startswith('univ') ) or \ ( location.address.startswith('Carnegie Mellon') and row.address.lower().startswith('carnegie mellon') ): location.address = ','.join(location.address.split(',')[1:]) try: # if exact match exists, use it instead of the newly found one location = Location.objects.get(address=location.address,postcode=location.postcode) except Location.DoesNotExist: location.save() else: print 'WARNING: Geocoding failed for entry %d ("%s")' % (i,row.place) diff_org = row.org != row.place org, place = None, None # import org # if the row has a fb id, we'll try to import the Org from Facebook # only import Org from Facebook if it's the same as the Place (fb id relates to place only) if row.fb_id and not diff_org: try: org = FacebookOrgRecord.objects.get(fb_id=row.fb_id) except FacebookOrgRecord.DoesNotExist: report = page_mgr.import_org(row.fb_id) if report.model_instance: org = report.model_instance else: print 'WARNING: Organization FB import failed for entry %d (fbid %s)' % (i,str(row.fb_id)) if not org: org,created = Organization.objects.get_or_create(name=row.org) # import place if row.fb_id: try: place = ExternalPlaceSource.facebook.get(uid=row.fb_id) except ExternalPlaceSource.DoesNotExist: report = page_mgr.import_place(row.fb_id,import_owners=False) if report.model_instance: place = report.model_instance if not place.owner: # no owner is created automatically, so set it if not created place.owner = org place.save() else: print 'WARNING: Place FB import failed for entry %d (fbid %s)' % (i,str(row.fb_id)) if not place: place,created = Place.objects.get_or_create(name=row.place,location=location,owner=org) if row.url: PlaceMeta.objects.create(place=place,meta_key='url',meta_value=row.url) if not diff_org: # also save the url as the org's url if they're the same org.url = row.url org.save() if row.phone: PlaceMeta.objects.create(place=place,meta_key='phone',meta_value=row.phone) print 'Imported %s' % row.place try: print ' (linked to FB page %s)' % ExternalPlaceSource.facebook.get(place=place).uid except ExternalPlaceSource.DoesNotExist: pass # store tags from Google Place lookup if location and \ location.latitude is not None and location.longitude is not None: coords = (location.latitude,location.longitude) radius = 1000 else: coords = (40.4425,-79.9575) radius = 5000 response = gplaces_client.search_request(coords,radius,keyword=row.place) if len(response) > 0 and 'reference' in response[0]: details = gplaces_client.details_request(response[0]['reference']) all_tags = set() for typ in details.get('types',[]): if typ in gplaces_category_map: all_tags.update(gplaces_category_map[typ]) else: print 'WARNING: Unknown Google Places type: "%s"' % typ if len(all_tags) > 0: print ' Tags:', for t in all_tags: print '%s,' % t, print gp_hits += 1 else: print ' WARNING: Failure querying Google Places for "%s" within %dm of (%f,%f)' % (row.place,radius,coords[0],coords[1]) gp_misses += 1 print gp_hits, gp_misses
def store_fbpage_place(page_info,create_owner=True): ''' Takes a dict of properties retreived from a Facebook Graph API call for a page and stores a Place from the information. The following fields in the dict are used: - id (required) - type (required with value 'page' or a TypeError will be thrown) - location (required or TypeError will be thrown) - description - url - phone - hours - picture No new Place will be returned if either an identical one already exists in the db, or an ExternalPlaceSource already exists for the given Facebook id. An INFO message is logged to note the attempt to store an existing page as a Place. If create_owner is True a new Organization will be created from the same page information if one does not already exist. ''' pid = page_info['id'] try: place = ExternalPlaceSource.objects.get(service='fb',uid=pid).place outsourcing_log.info('Existing fb page Place found for fbid %s' % unicode(pid)) return place except ExternalPlaceSource.DoesNotExist: pass if page_info.get('type') != 'page': raise TypeError("Cannot store object without 'page' type as a Place.") elif 'location' not in page_info: raise TypeError("Cannot store object without location key as a Place.") pname = page_info['name'].strip() ### Figure out the new Place's location field fbloc = page_info['location'] if 'id' in fbloc: # TODO: need to ensure fbloc_to_loc can handle ids in location if this ever happens outsourcing_log.info('Facebook page %s has id in location (%s)' % (pid,fbloc['id'])) location = fbloc_to_loc(fbloc) # if there's no address or geocoding, we'll need to talk to outside services if not location.address: seed_place = Place(name=pname,location=location) resolved_place = resolve_place(seed_place) if resolved_place: location = resolved_place.location # really want geolocation, go to Google Geocoding for it if we need it if location.longitude is None or location.latitude is None: seed_loc = copy.deepcopy(location) resolved_location = resolve_location(seed_loc,allow_numberless=False) if resolved_location: location = resolved_location # if there's no specific address information, make the error radius around the # lat/lng super tight. Don't want to create whirlpools. cl_opts = dict(lat_error=1e-5,lng_error=1e-5) if not location.address else {} location, created = Location.close_manager.get_close_or_create( address=location.address, postcode=location.postcode, town=location.town, state=location.state, country=location.country, neighborhood=location.neighborhood, latitude=location.latitude, longitude=location.longitude, _close_options=cl_opts) if created: outsourcing_log.debug('Saved new location "%s"' % location.full_string) else: outsourcing_log.debug('Retrieved existing location "%s"' % location.full_string) try: owner = FacebookOrgRecord.objects.get(fb_id=pid).organization except FacebookOrgRecord.DoesNotExist: if create_owner: outsourcing_log.info('Creating new Organization as byproduct of creating Place from Facebook page %s' % unicode(pid)) owner = store_fbpage_organization(page_info) else: owner = None place, created = Place.objects.get_or_create(name=pname[:200], description=page_info.get('description','').strip(), location=location, owner=owner) # add place meta info that exists _store_fbpage_placemeta(page_info,place) # create a new link to an external id ExternalPlaceSource.objects.create(service='fb',uid=pid, place=place) return place
def _process_place(event_info): ''' Attempts to tease a Place out of the given event_info. May return either an already stored Place or a non-stored one (check the pk value to tell the difference). Important! If Place is not yet stored, the Location inside it is not guaranteed to be stored either. Ensure the inner Location is saved before saving the Place! ''' venue = event_info.get('venue',{}) place_name = event_info.get('location','').strip() if venue.get('id'): # best case is that our venue is identified by an existing Facebook ID try: return ExternalPlaceSource.facebook.get(uid=venue.get('id')).place except ExternalPlaceSource.DoesNotExist: pass # we couldn't get a nice id-based Place, so we're going to try to figure one # out manually if there's vanue or place_name fields if venue or place_name: # do something semi-intelligent to get a good Location out of the venue if venue: location = fbpages.fbloc_to_loc(venue) # if there's no address or geocoding, we'll need to talk to outside services if not location.address: # try to build a seed to resolve with seed_loc = copy.deepcopy(location) # in the absense of city/state info, assume location is in same city/state as owner if not seed_loc.town or not seed_loc.state: fbowner = event_info.get('owner',{}) if fbowner.get('id'): try: owner_place = ExternalPlaceSource.facebook.get(uid=fbowner.get('id')).place except ExternalPlaceSource.DoesNotExist: owner_place = None if owner_place: if not seed_loc.town: seed_loc.town = owner_place.location.town if not seed_loc.state: seed_loc.state = owner_place.location.state seed_place = Place(name=place_name,location=seed_loc) resolved_place = resolve_place(seed_place) if resolved_place: # throw awy everything but the location location = resolved_place.location # really want geolocation, go to Google Geocoding for it if we need it if location.longitude is None or location.latitude is None: seed_loc = copy.deepcopy(location) resolved_location = resolve_location(seed_loc) if resolved_location: location = resolved_location # if there's a "close enough" location in the db already, find and use it # only want to include "not-null" arguments into the get_close call. find these here # if still no geocoding info, has_geocoding = location.latitude is not None and location.longitude is not None if has_geocoding: # since we've got geocoding info, this location is specific. therefore, null entries # just signify a lack of info, not a planned null field for a vague address: omit them # for the get query kwargs = _location_to_kwargs(location,True) try: location = Location.close_manager.get_close(**kwargs) except Location.DoesNotExist: # if none found, no biggie, just return pass else: # if we don't have geocoding, we want to find an exact match in the db, null fields and all kwargs = _location_to_kwargs(location,False) try: location = Location.objects.get(**kwargs) except Location.DoesNotExist: # if none found, no biggie, just return pass except Location.MultipleObjectsReturned: # if more than one found, its a sign there's some dups in the db. just return the first one. outsourcing_log.warning('Multiple objects returned with Location query of %s' % unicode(kwargs)) return Location.objects.filter(**kwargs)[0] else: location = None return Place(name=place_name,location=location) # worst case: we assume the event is happening at the location specified by the # owners fbid (assuming this fbid is already linked to a place) fbowner_id = event_info.get('owner',{}).get('id') if fbowner_id: # TODO: try harder to resolve owner place? isolated event creation will always fail here try: return ExternalPlaceSource.facebook.get(uid=fbowner_id).place except ExternalPlaceSource.DoesNotExist: pass return None
def _process_place(event_info): ''' Attempts to tease a Place out of the given event_info. May return either an already stored Place or a non-stored one (check the pk value to tell the difference). Important! If Place is not yet stored, the Location inside it is not guaranteed to be stored either. Ensure the inner Location is saved before saving the Place! ''' venue = event_info.get('venue', {}) place_name = event_info.get('location', '').strip() if venue.get('id'): # best case is that our venue is identified by an existing Facebook ID try: return ExternalPlaceSource.facebook.get(uid=venue.get('id')).place except ExternalPlaceSource.DoesNotExist: pass # we couldn't get a nice id-based Place, so we're going to try to figure one # out manually if there's vanue or place_name fields if venue or place_name: # do something semi-intelligent to get a good Location out of the venue if venue: location = fbpages.fbloc_to_loc(venue) # if there's no address or geocoding, we'll need to talk to outside services if not location.address: # try to build a seed to resolve with seed_loc = copy.deepcopy(location) # in the absense of city/state info, assume location is in same city/state as owner if not seed_loc.town or not seed_loc.state: fbowner = event_info.get('owner', {}) if fbowner.get('id'): try: owner_place = ExternalPlaceSource.facebook.get( uid=fbowner.get('id')).place except ExternalPlaceSource.DoesNotExist: owner_place = None if owner_place: if not seed_loc.town: seed_loc.town = owner_place.location.town if not seed_loc.state: seed_loc.state = owner_place.location.state seed_place = Place(name=place_name, location=seed_loc) resolved_place = resolve_place(seed_place) if resolved_place: # throw awy everything but the location location = resolved_place.location # really want geolocation, go to Google Geocoding for it if we need it if location.longitude is None or location.latitude is None: seed_loc = copy.deepcopy(location) resolved_location = resolve_location(seed_loc) if resolved_location: location = resolved_location # if there's a "close enough" location in the db already, find and use it # only want to include "not-null" arguments into the get_close call. find these here # if still no geocoding info, has_geocoding = location.latitude is not None and location.longitude is not None if has_geocoding: # since we've got geocoding info, this location is specific. therefore, null entries # just signify a lack of info, not a planned null field for a vague address: omit them # for the get query kwargs = _location_to_kwargs(location, True) try: location = Location.close_manager.get_close(**kwargs) except Location.DoesNotExist: # if none found, no biggie, just return pass else: # if we don't have geocoding, we want to find an exact match in the db, null fields and all kwargs = _location_to_kwargs(location, False) try: location = Location.objects.get(**kwargs) except Location.DoesNotExist: # if none found, no biggie, just return pass except Location.MultipleObjectsReturned: # if more than one found, its a sign there's some dups in the db. just return the first one. outsourcing_log.warning( 'Multiple objects returned with Location query of %s' % unicode(kwargs)) return Location.objects.filter(**kwargs)[0] else: location = None return Place(name=place_name, location=location) # worst case: we assume the event is happening at the location specified by the # owners fbid (assuming this fbid is already linked to a place) fbowner_id = event_info.get('owner', {}).get('id') if fbowner_id: # TODO: try harder to resolve owner place? isolated event creation will always fail here try: return ExternalPlaceSource.facebook.get(uid=fbowner_id).place except ExternalPlaceSource.DoesNotExist: pass return None