def geocode(request): geocode = Geocode() if request.GET.get('search'): result = geocode.search(request.GET.get('search')) return HttpResponse(content=json.dumps(result), status=200, content_type="application/json") if request.GET.get('result'): result = geocode.add_bbox(json.loads(request.GET.get('result'))) return HttpResponse(content=json.dumps(result), status=200, content_type="application/json") else: return HttpResponse(status=204, content_type="application/json")
def geocode_test(self, api_response): self.mock_requests.get(settings.GEOCODING_API_URL, text=json.dumps(api_response), status_code=200) geocode = Geocode() result = geocode.search("test") self.assertIsNotNone(result.get("features")) self.assertEqual(result.get("type"), "FeatureCollection") self.assertIsInstance(result.get("bbox"), list) for feature in result.get("features"): self.assertIsInstance(feature.get("bbox"), list) properties = feature.get("properties") self.assertIsInstance(properties, dict) self.assertIsNotNone(feature.get('geometry')) for property in GeocodeAdapter._properties: self.assertTrue(property in properties)
def geocode_test(self, api_response, mock_get_session): mock_get_session.return_value = self.session self.adapter.register_uri("GET", settings.GEOCODING_API_URL, text=json.dumps(api_response), status_code=200) geocode = Geocode() result = geocode.search("test") self.assertIsNotNone(result.get("features")) self.assertEqual(result.get("type"), "FeatureCollection") self.assertIsInstance(result.get("bbox"), list) for feature in result.get("features"): self.assertIsInstance(feature.get("bbox"), list) properties = feature.get("properties") self.assertIsInstance(properties, dict) self.assertIsNotNone(feature.get("geometry")) self.assertIsNotNone(feature.get("properties", {}).get("context_name")) for property in GeocodeAdapter._properties: self.assertTrue(property in properties)
def test_pelias_polygon_geometry(self, mock_get_session): mock_get_session.return_value = self.session polygonCoordinates = [[[0, 1], [1, 0], [0, 3]]] bbox = [-71.1912490997, 42.227911131, -70.9227798807, 42.3969775021] api_response = { "features": [ { "type": "Feature", "geometry": {"type": "Polygon", "coordinates": polygonCoordinates}, "properties": {}, "bbox": bbox, } ] } self.adapter.register_uri("GET", settings.GEOCODING_API_URL, text=json.dumps(api_response), status_code=200) geocode = Geocode() result = geocode.search("test") self.assertEqual(result.get("features")[0].get("geometry").get("coordinates"), polygonCoordinates)
def test_pelias_point_geometry(self): bbox = [-71.1912490997, 42.227911131, -70.9227798807, 42.3969775021] api_response = { "features": [ { "type": "Feature", "geometry": { "type":"Point", "coordinates": [] }, "bbox": bbox } ] } self.mock_requests.get(settings.GEOCODING_API_URL, text=json.dumps(api_response), status_code=200) geocode = Geocode() result = geocode.search("test") self.assertEqual(result.get('features')[0].get('geometry').get('coordinates'), [[[-71.1912490997, 42.227911131], [-70.9227798807, 42.227911131], [-70.9227798807, 42.3969775021], [-71.1912490997, 42.3969775021], [-71.1912490997, 42.227911131]]])
def test_pelias_polygon_geometry(self): polygonCoordinates = [[[0, 1], [1, 0], [0, 3]]] bbox = [-71.1912490997, 42.227911131, -70.9227798807, 42.3969775021] api_response = { "features": [{ "type": "Feature", "geometry": { "type": "Polygon", "coordinates": polygonCoordinates }, "bbox": bbox }] } self.mock_requests.get(settings.GEOCODING_API_URL, text=json.dumps(api_response), status_code=200) geocode = Geocode() result = geocode.search("test") self.assertEqual( result.get('features')[0].get('geometry').get('coordinates'), polygonCoordinates)
def search(request): """ Detects the query type and calls the relevant geocoder to get results :param request: User request which should include a query parameter :return: A geojson with features matching the search query """ q = request.GET.get('query', None) if not q: return HttpResponse(status=204, content_type="application/json") error_string = "An unknown error occurred while querying for results, please contact an administrator." degree_range = 0.05 if is_mgrs(q): # check for necessary settings if getattr(settings, 'CONVERT_API_URL') is None: return HttpResponse('No Convert API specified', status=501) if getattr(settings, 'REVERSE_GEOCODING_API_URL') is None: return HttpResponse('No Reverse Geocode API specified', status=501) # make call to convert which should return a geojson feature of the MGRS location convert = CoordinateConverter() try: mgrs_data = convert.get(q) except Exception: return HttpResponse(content=error_string, status=500) # if no feature geom return nothing if not mgrs_data or not mgrs_data.get('geometry'): return HttpResponse(status=204, content_type="application/json") features = [] # save the mgrs feature to return later if not mgrs_data.get('properties'): mgrs_data['properties'] = {} mgrs_data['properties']['bbox'] = [ mgrs_data.get('geometry').get('coordinates')[0] - degree_range, mgrs_data.get('geometry').get('coordinates')[1] - degree_range, mgrs_data.get('geometry').get('coordinates')[0] + degree_range, mgrs_data.get('geometry').get('coordinates')[1] + degree_range ] mgrs_data['source'] = 'MGRS' features.append(mgrs_data) # call reverse to get a list of results near the mgrs feature reverse = ReverseGeocode() try: result = reverse.search({ "point.lat": mgrs_data.get('geometry').get('coordinates')[1], "point.lon": mgrs_data.get('geometry').get('coordinates')[0] }) except Exception: return HttpResponse(content=error_string, status=500) if result.get('features'): # add the mgrs feature with the search results and return together result['features'] = features + result['features'] return HttpResponse(content=json.dumps(result), status=200, content_type="application/json") # if no results just return the MGRS feature in the response return HttpResponse(content=json.dumps({'features': features}), status=200, content_type="application/json") elif is_lat_lon(q): coords = is_lat_lon(q) # if no reverse url return 501 if getattr(settings, 'REVERSE_GEOCODING_API_URL') is None: return HttpResponse('No Reverse Geocode API specified', status=501) # make call to reverse geocode reverse = ReverseGeocode() try: result = reverse.search({ "point.lat": coords[0], "point.lon": coords[1] }) except Exception: return HttpResponse(content=error_string, status=500) # create a feature representing the exact lat/lon being searched point_feature = { "geometry": { "type": "Point", "coordinates": [coords[1], coords[0]] }, "source": "Coordinate", "type": "Feature", "properties": { "name": "{0} {1}, {2} {3}".format( coords[0] if coords[0] >= 0 else coords[0] * -1, "N" if coords[0] >= 0 else "S", coords[1] if coords[1] >= 0 else coords[1] * -1, "E" if coords[1] >= 0 else "W"), "bbox": [ coords[1] - degree_range, coords[0] - degree_range, coords[1] + degree_range, coords[0] + degree_range ] } } # if there are results add the point feature and return them together if result.get('features'): result.get('features').insert(0, point_feature) return HttpResponse(content=json.dumps(result), status=200, content_type="application/json") # if there are no results return only the point feature features = {'features': [point_feature]} return HttpResponse(content=json.dumps(features), status=200, content_type="application/json") else: # make call to geocode with search geocode = Geocode() try: result = geocode.search(q) except Exception as e: logger.error(e) return HttpResponse(content=error_string, status=500) return HttpResponse(content=json.dumps(result), status=200, content_type="application/json")
def search(request): """ Detects the query type and calls the relevant geocoder to get results :param request: User request which should include a query parameter :return: A geojson with features matching the search query """ q = request.GET.get('query', None) if not q: return HttpResponse(status=204, content_type="application/json") error_string = "An unknown error occurred while querying for results, please contact an administrator." degree_range = 0.05 if is_mgrs(q): # check for necessary settings if getattr(settings, 'CONVERT_API_URL') is None: return HttpResponse('No Convert API specified', status=501) if getattr(settings, 'REVERSE_GEOCODING_API_URL') is None: return HttpResponse('No Reverse Geocode API specified', status=501) # make call to convert which should return a geojson feature of the MGRS location convert = CoordinateConverter() try: mgrs_data = convert.get(q) except Exception: return HttpResponse( content=error_string, status=500 ) # if no feature geom return nothing if not mgrs_data or not mgrs_data.get('geometry'): return HttpResponse(status=204, content_type="application/json") features = [] # save the mgrs feature to return later if not mgrs_data.get('properties'): mgrs_data['properties'] = {} mgrs_data['properties']['bbox'] = [ mgrs_data.get('geometry').get('coordinates')[0] - degree_range, mgrs_data.get('geometry').get('coordinates')[1] - degree_range, mgrs_data.get('geometry').get('coordinates')[0] + degree_range, mgrs_data.get('geometry').get('coordinates')[1] + degree_range ] mgrs_data['source'] = 'MGRS' features.append(mgrs_data) # call reverse to get a list of results near the mgrs feature reverse = ReverseGeocode() try: result = reverse.search({ "point.lat": mgrs_data.get('geometry').get('coordinates')[1], "point.lon": mgrs_data.get('geometry').get('coordinates')[0] }) except Exception: return HttpResponse( content=error_string, status=500 ) if result.get('features'): # add the mgrs feature with the search results and return together result['features'] = features + result['features'] return HttpResponse(content=json.dumps(result), status=200, content_type="application/json") # if no results just return the MGRS feature in the response return HttpResponse(content=json.dumps({'features': features}), status=200, content_type="application/json") elif is_lat_lon(q): coords = is_lat_lon(q) # if no reverse url return 501 if getattr(settings, 'REVERSE_GEOCODING_API_URL') is None: return HttpResponse('No Reverse Geocode API specified', status=501) # make call to reverse geocode reverse = ReverseGeocode() try: result = reverse.search({ "point.lat": coords[0], "point.lon": coords[1] }) except Exception: return HttpResponse( content=error_string, status=500 ) # create a feature representing the exact lat/lon being searched point_feature = { "geometry": { "type": "Point", "coordinates": [coords[1], coords[0]] }, "source": "Coordinate", "type": "Feature", "properties": { "name": "{0} {1}, {2} {3}".format( coords[0] if coords[0] >= 0 else coords[0] * -1, "N" if coords[0] >= 0 else "S", coords[1] if coords[1] >= 0 else coords[1] * -1, "E" if coords[1] >= 0 else "W" ), "bbox": [ coords[1] - degree_range, coords[0] - degree_range, coords[1] + degree_range, coords[0] + degree_range ] } } # if there are results add the point feature and return them together if result.get('features'): result.get('features').insert(0, point_feature) return HttpResponse(content=json.dumps(result), status=200, content_type="application/json") # if there are no results return only the point feature features = {'features': [point_feature]} return HttpResponse(content=json.dumps(features), status=200, content_type="application/json") else: # make call to geocode with search geocode = Geocode() try: result = geocode.search(q) except Exception as e: logger.error(e) return HttpResponse( content=error_string, status=500 ) return HttpResponse(content=json.dumps(result), status=200, content_type="application/json")