Hands On

Discovering nearby Places using Python Flask

By Vidhan Bhonsle | 26 May 2020

What is the best feature you like in a modern mobile application? There may be a lot, but my favorite is when an application shows up nearby places on a map without typing a single word. All you need to do is to enable location feature on mobile and app shows you the results on the map. This feature saves a lot of time. Consider a scenario where you need a medical service and you are looking for a hospital nearby. What will you do? Open a medical service app and search for a nearby hospital. Application will show you all the hospitals near to your location and you will select one based on the popped-up information. This is exactly what we are going to learn in this blog using Discover endpoint of Geocoding and Search API. We will create a Python Flask application to show hospitals in the vicinity of a provided location. Let us get started!

Prerequisites

Your machine should have Python installed (I have Python 3.8) and if you haven't done so yet, you will need to sign up for a Freemium account on developer.here.com. Once you have signed up, you can generate your free API key and get 250.000 free transactions every month.

Discover Endpoint of Geocoding and Search API

Discover simplifies searching for places by letting you search for a known or an unknown place. All you need is to submit a free-form text request that returns a JSON response containing places along with additional details.

 


https://discover.search.hereapi.com/v1/discover
?at=12.96643,77.5871
&q=hospital
&apikey=YOUR_API_KEY
&limit=5
  • at: Latitude and longitude value separated by a comma
  • q: A place you are looking for, we are searching for hospitals near provided latitude and longitude.
  • apikey: From the Freemium account generated on developer portal
  • limit: Limits the number of result, we are limiting it to 5. 

The REST API will return a JSON response containing nearest hospitals along with additional details.    


...
{
  "items": [
    {
      "title": "ST. Martha's Hospital",
      "id": "here:pds:place:356tdr1v-021cdf05fe1a453a9f2124eeff3e3182",
      "resultType": "place",
      "address": {
        "label": "ST. Martha's Hospital, Sampangi Rama Nagar, Bengaluru 560027, India",
        "countryCode": "IND",
        "countryName": "India",
        "state": "Karnataka",
        "county": "Bengaluru",
        "city": "Bengaluru",
        "district": "Sampangi Rama Nagar",
        "postalCode": "560027"
      },
      "position": {
        "lat": 12.97076,
        "lng": 77.58637
      },
      "access": [
        {
          "lat": 12.97077,
          "lng": 77.58639
        }
      ],
      "distance": 488,
      "categories": [
        {
          "id": "800-8000-0159"
        }
      ]
    },
    {
      "title": "Mallya Hospital",
      "id": "here:pds:place:356tdr1v-0a1c39a1306f4046a0d76e1828afc7ba",
      "resultType": "place",
      "address": {
        "label": "Mallya Hospital, Vittal Mallya Road, Ashoka Nagar, Bengaluru 560001, India",
        "countryCode": "IND",
        "countryName": "India",
        "state": "Karnataka",
        "county": "Bengaluru",
        "city": "Bengaluru",
        "district": "Ashoka Nagar",
        "street": "Vittal Mallya Road",
        "postalCode": "560001"
      },
      "position": {
        "lat": 12.96769,
        "lng": 77.59493
      },
      "access": [
        {
          "lat": 12.96803,
          "lng": 77.59482
        }
      ],
      "distance": 860,
      "categories": [
        {
          "id": "800-8000-0000"
        },
        {
          "id": "800-8000-0158"
        },
        {
          "id": "800-8000-0159"
        }
      ],
      "contacts": [
        {
          "phone": [
            {
              "value": "+918022277979"
            }
          ],
          "mobile": [
            {
              "value": "+918022221564"
            }
          ],
          "fax": [
            {
              "value": "+918022121282"
            }
          ],
          "www": [
            {
              "value": "http://www.mallyahospital.net"
            }
          ],
          "email": [
            {
              "value": "mallya@giashg01.vsnl.net.in"
            }
          ]
        }
      ]
    },
    {
      "title": "Republic Hospital",
      "id": "here:pds:place:356tdr1v-d742487af5274445b899852b66f64f13",
      "resultType": "place",
      "address": {
        "label": "Republic Hospital, Langford Gardens, Richmond Town, Bengaluru 560025, India",
        "countryCode": "IND",
        "countryName": "India",
        "state": "Karnataka",
        "county": "Bengaluru",
        "city": "Bengaluru",
        "district": "Richmond Town",
        "subdistrict": "Langford Gardens",
        "postalCode": "560025"
      },
      "position": {
        "lat": 12.96415,
        "lng": 77.59799
      },
      "access": [
        {
          "lat": 12.96416,
          "lng": 77.59797
        }
      ],
      "distance": 1207,
      "categories": [
        {
          "id": "800-8000-0000"
        },
        {
          "id": "800-8000-0157"
        },
        {
          "id": "800-8000-0158"
        },
        {
          "id": "800-8000-0159"
        }
      ],
      "contacts": [
        {
          "phone": [
            {
              "value": "+918022211762"
            },
            {
              "value": "+918046808354"
            }
          ],
          "www": [
            {
              "value": "HTTPS://WWW.REPUBLICHOSPITAL.IN"
            }
          ]
        }
      ]
    },
    {
      "title": "Vanivilas Hospital",
      "id": "here:pds:place:356tdr1t-59db4ec93a3246c5bcf4940ce26b088b",
      "resultType": "place",
      "address": {
        "label": "Vanivilas Hospital, New Tharagupet, Kalasipalyam, Bengaluru 560002, India",
        "countryCode": "IND",
        "countryName": "India",
        "state": "Karnataka",
        "county": "Bengaluru",
        "city": "Bengaluru",
        "district": "Kalasipalyam",
        "subdistrict": "New Tharagupet",
        "postalCode": "560002"
      },
      "position": {
        "lat": 12.96244,
        "lng": 77.57396
      },
      "access": [
        {
          "lat": 12.96246,
          "lng": 77.57395
        }
      ],
      "distance": 1491,
      "categories": [
        {
          "id": "800-8000-0000"
        },
        {
          "id": "800-8000-0158"
        },
        {
          "id": "800-8000-0159"
        }
      ],
      "contacts": [
        {
          "phone": [
            {
              "value": "+918026708395"
            }
          ]
        }
      ]
    },
    {
      "title": "विक्टोरिया हॉस्पिटल",
      "id": "here:pds:place:356tdr1t-7782433d22eb4d5aaa3d5c57ed3c1df9",
      "resultType": "place",
      "address": {
        "label": "विक्टोरिया हॉस्पिटल, New Tharagupet, Kalasipalyam, Bengaluru 560002, India",
        "countryCode": "IND",
        "countryName": "India",
        "state": "Karnataka",
        "county": "Bengaluru",
        "city": "Bengaluru",
        "district": "Kalasipalyam",
        "subdistrict": "New Tharagupet",
        "postalCode": "560002"
      },
      "position": {
        "lat": 12.96305,
        "lng": 77.57281
      },
      "access": [
        {
          "lat": 12.96304,
          "lng": 77.57279
        }
      ],
      "distance": 1593,
      "categories": [
        {
          "id": "800-8000-0159"
        }
      ],
      "contacts": [
        {
          "phone": [
            {
              "value": "+918026701150"
            }
          ],
          "www": [
            {
              "value": "http://www.victoriahospitalbangalore.org"
            }
          ]
        }
      ]
    }
  ]
}

 The above JSON response shows details of 5 hospitals in an area of Bangalore, India.

Working with Python

We are using Python for making API call and parsing the response data. For this, install the requests library with 'pip install requests' command using Python IDE (PyCharm, Spyder, etc) or terminal/command prompt depending on how you are working on Python (I am using the command prompt), and then import it in the code.


import requests

URL = "https://discover.search.hereapi.com/v1/discover"
latitude = 12.96643
longitude = 77.5871
api_key = 'YOUR_API_KEY' # Acquire from developer.here.com
query = 'hospitals'
limit = 5

PARAMS = {
            'apikey':api_key,
            'q':query,
            'limit': limit,
            'at':'{},{}'.format(latitude,longitude)
         } 

# sending get request and saving the response as response object 
r = requests.get(url = URL, params = PARAMS) 
data = r.json()


hospitalOne = data['items'][0]['title']
hospitalOne_address =  data['items'][0]['address']['label']
hospitalOne_latitude = data['items'][0]['position']['lat']
hospitalOne_longitude = data['items'][0]['position']['lng']


hospitalTwo = data['items'][1]['title']
hospitalTwo_address =  data['items'][1]['address']['label']
hospitalTwo_latitude = data['items'][1]['position']['lat']
hospitalTwo_longitude = data['items'][1]['position']['lng']

hospitalThree = data['items'][2]['title']
hospitalThree_address =  data['items'][2]['address']['label']
hospitalThree_latitude = data['items'][2]['position']['lat']
hospitalThree_longitude = data['items'][2]['position']['lng']


hospitalFour = data['items'][3]['title']
hospitalFour_address =  data['items'][3]['address']['label']
hospitalFour_latitude = data['items'][3]['position']['lat']
hospitalFour_longitude = data['items'][3]['position']['lng']

hospitalFive = data['items'][4]['title']
hospitalFive_address =  data['items'][4]['address']['label']
hospitalFive_latitude = data['items'][4]['position']['lat']
hospitalFive_longitude = data['items'][4]['position']['lng']

Introducing Flask

We have acquired all the values needed (hospital name, hospital address, latitude, longitude, API key) to show on our map. This can be done easily with the help of flask.

All we need to do is install a library named flask, with 'pip install flask' command.

Now, let’s integrate all the values collected so far into the flask code.


from flask import Flask,render_template

app = Flask(__name__)
@app.route('/')

def map_func():
	return render_template('map.html',
    			latitude=latitude,
                            longitude=longitude,
                            apikey=api_key,
                            oneName=hospitalOne,
                            OneAddress=hospitalOne_address,
                            oneLatitude=hospitalOne_latitude,
                            oneLongitude=hospitalOne_longitude,
                            twoName=hospitalTwo,
                            twoAddress=hospitalTwo_address,
                            twoLatitude=hospitalTwo_latitude,
                            twoLongitude=hospitalTwo_longitude,
                            threeName=hospitalThree,
                            threeAddress=hospitalThree_address,
                            threeLatitude=hospitalThree_latitude,
                            threeLongitude=hospitalThree_longitude,
                            fourName=hospitalFour,		
                            fourAddress=hospitalFour_address,
                            fourLatitude=hospitalFour_latitude,
                            fourLongitude=hospitalFour_longitude,
                            fiveName=hospitalFive,		
                            fiveAddress=hospitalFive_address,
                            fiveLatitude=hospitalFive_latitude,
                            fiveLongitude=hospitalFive_longitude)

if __name__ == '__main__':
	app.run(debug = False)
    

The above code represents a simple flask template in which we have imported two sub-packages of flask, viz., Flask and render_template. Also, we have created a function called the “map_func”. This function returns a jinga2 html page and passes the API Key, latitude and longitude to our HTML code (yes, we will need HTML too).

Working with HTML and JavaScript

A HTML file will be required to show the Map on the browser. For this, we need to create an HTML file in a folder called “templates”, and then name the file as “map.html”


<html>  
<head>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
<script src="https://js.api.here.com/v3/3.1/mapsjs-core.js"type="text/javascript" charset="utf-8"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-service.js"type="text/javascript" charset="utf-8"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js" type="text/javascript" charset="utf-8"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-ui.js" type="text/javascript" charset="utf-8"></script>
<link rel="stylesheet" type="text/css"href="https://js.api.here.com/v3/3.1/mapsjs-ui.css" />
</head>
  
<body style='margin: 0'>
<div style="width: 100%; height: 100%" id="mapContainer"></div>

<script>	
      // Initialize the platform object:
      var platform = new H.service.Platform({
        'apikey': '{{apikey}}'
      });
	  
	   const lat = {{latitude}};
	   const lng = {{longitude}};
	   
	   const hospitalOne_lat = {{oneLatitude}}; 
	   const hospitalOne_lng = {{oneLongitude}};

	   const hospitalTwo_lat = {{twoLatitude}}; 
	   const hospitalTwo_lng = {{twoLongitude}};

	   const hospitalThree_lat = {{threeLatitude}}; 
	   const hospitalThree_lng = {{threeLongitude}};

	   const hospitalFour_lat = {{fourLatitude}}; 
	   const hospitalFour_lng = {{fourLongitude}};

	   const hospitalFive_lat = {{fiveLatitude}}; 
	   const hospitalFive_lng = {{fiveLongitude}};	   
	
	// Obtain the default map types from the platform object
      var maptypes = platform.createDefaultLayers();

      // Initialize a map:
      var map = new H.Map(
        document.getElementById('mapContainer'),
        maptypes.raster.terrain.map,
        {
          zoom: 15,
          center: { lat: lat, lng: lng }  
        });
		
	// Enable the event system on the map instance:
	  var mapEvents = new H.mapevents.MapEvents(map);
	
	// Instantiate the default behavior, providing the mapEvents object:
	 var behavior = new H.mapevents.Behavior(mapEvents);

	var myLocation_marker = new H.map.Marker({ lat: lat, lng: lng });
	var hospitalOne_marker = new H.map.Marker({ lat: hospitalOne_lat, lng: hospitalOne_lng });
	var hospitalTwo_marker = new H.map.Marker({ lat: hospitalTwo_lat, lng: hospitalTwo_lng });
	var hospitalThree_marker = new H.map.Marker({ lat: hospitalThree_lat, lng: hospitalThree_lng });
	var hospitalFour_marker = new H.map.Marker({ lat: hospitalFour_lat, lng: hospitalFour_lng });
	var hospitalFive_marker = new H.map.Marker({ lat: hospitalFive_lat, lng: hospitalFour_lng });
		
	// Add the marker to the map:
	map.addObject(myLocation_marker);
	map.addObject(hospitalOne_marker);
	map.addObject(hospitalTwo_marker);
	map.addObject(hospitalThree_marker);
	map.addObject(hospitalFour_marker);
	map.addObject(hospitalFive_marker);
	
	// Create the default UI:
	var ui = H.ui.UI.createDefault(map, maptypes);
	
	// Add event listener to the marker:
	myLocation_marker.addEventListener('tap', function(evt) {
    
		// Create an info bubble object at a specific geographic location:
		var bubble = new H.ui.InfoBubble({ lng: lng, lat: lat }, {
                content: ''
             });
		bubble.setContent('<div style="height: 130px; overflow: auto; width: 270px;"><h3>"Hi"</h3><p>"This is you!"</p></div>');
		// Add info bubble to the UI:
		ui.addBubble(bubble);
	});	
	
hospitalOne_marker.addEventListener('tap', function(evt) {
    
		// Create an info bubble object at a specific geographic location:
		var bubble = new H.ui.InfoBubble({ lng: hospitalOne_lng, lat: hospitalOne_lat }, {
                content: ''
             });
		bubble.setContent('<div style="height: 130px; overflow: auto; width: 270px;"><h3>{{oneName}}</h3><p>{{oneAddress}}</p></div>');
		// Add info bubble to the UI:
		ui.addBubble(bubble);
	});
	
hospitalTwo_marker.addEventListener('tap', function(evt) {
    
		// Create an info bubble object at a specific geographic location:
		var bubble = new H.ui.InfoBubble({ lng: hospitalTwo_lng, lat: hospitalTwo_lat }, {
                content: ''
             });
		bubble.setContent('<div style="height: 130px; overflow: auto; width: 270px;"><h3>{{twoName}}</h3><p>{{twoAddress}}</p></div>');
		// Add info bubble to the UI:
		ui.addBubble(bubble);
	});
	
hospitalThree_marker.addEventListener('tap', function(evt) {
    
		// Create an info bubble object at a specific geographic location:
		var bubble = new H.ui.InfoBubble({ lng: hospitalThree_lng, lat: hospitalThree_lat }, {
                content: ''
             });
		bubble.setContent('<div style="height: 130px; overflow: auto; width: 270px;"><h3>{{threeName}}</h3><p>{{threeAddress}}</p></div>');
		// Add info bubble to the UI:
		ui.addBubble(bubble);
	});
	
hospitalFour_marker.addEventListener('tap', function(evt) {
    
		// Create an info bubble object at a specific geographic location:
		var bubble = new H.ui.InfoBubble({ lng: hospitalFour_lng, lat: hospitalFour_lat }, {
                content: ''
             });
		bubble.setContent('<div style="height: 130px; overflow: auto; width: 270px;"><h3>{{fourName}}</h3><p>{{fourAddress}}</p></div>');
		// Add info bubble to the UI:
		ui.addBubble(bubble);
	});
	
hospitalFive_marker.addEventListener('tap', function(evt) {
    
		// Create an info bubble object at a specific geographic location:
		var bubble = new H.ui.InfoBubble({ lng: hospitalFive_lng, lat: hospitalFive_lat }, {
                content: ''
             });
		bubble.setContent('<div style="height: 130px; overflow: auto; width: 270px;"><h3>{{fiveName}}</h3><p>{{fiveAddress}}</p></div>');
		// Add info bubble to the UI:
		ui.addBubble(bubble);
	});

</script>
</body>
</html>

The above code plots the latitude and longitude of 5 hospitals on a map and shows a marker on the plotted location. When marker is clicked, a box pops up showing the name and address of hospitals.

Complete Python Code


import requests
from flask import Flask,render_template
URL = "https://discover.search.hereapi.com/v1/discover"
latitude = 12.96643
longitude = 77.5871
api_key = 'YOUR_API_KEY' # Acquire from developer.here.com
query = 'hospital'
limit = 5

PARAMS = {
            'apikey':api_key,
            'q':query,
            'limit': limit,
            'at':'{},{}'.format(latitude,longitude)
         } 

# sending get request and saving the response as response object 
r = requests.get(url = URL, params = PARAMS) 
data = r.json()


hospitalOne = data['items'][0]['title']
hospitalOne_address =  data['items'][0]['address']['label']
hospitalOne_latitude = data['items'][0]['position']['lat']
hospitalOne_longitude = data['items'][0]['position']['lng']


hospitalTwo = data['items'][1]['title']
hospitalTwo_address =  data['items'][1]['address']['label']
hospitalTwo_latitude = data['items'][1]['position']['lat']
hospitalTwo_longitude = data['items'][1]['position']['lng']

hospitalThree = data['items'][2]['title']
hospitalThree_address =  data['items'][2]['address']['label']
hospitalThree_latitude = data['items'][2]['position']['lat']
hospitalThree_longitude = data['items'][2]['position']['lng']


hospitalFour = data['items'][3]['title']
hospitalFour_address =  data['items'][3]['address']['label']
hospitalFour_latitude = data['items'][3]['position']['lat']
hospitalFour_longitude = data['items'][3]['position']['lng']

hospitalFive = data['items'][4]['title']
hospitalFive_address =  data['items'][4]['address']['label']
hospitalFive_latitude = data['items'][4]['position']['lat']
hospitalFive_longitude = data['items'][4]['position']['lng']

app = Flask(__name__)
@app.route('/')

def map_func():
	return render_template('map.html',
                            latitude = latitude,
                            longitude = longitude,
                            apikey=api_key,
                            oneName=hospitalOne,
                            OneAddress=hospitalOne_address,
                            oneLatitude=hospitalOne_latitude,
                            oneLongitude=hospitalOne_longitude,
                            twoName=hospitalTwo,
                            twoAddress=hospitalTwo_address,
                            twoLatitude=hospitalTwo_latitude,
                            twoLongitude=hospitalTwo_longitude,
                            threeName=hospitalThree,
                            threeAddress=hospitalThree_address,
                            threeLatitude=hospitalThree_latitude,
                            threeLongitude=hospitalThree_longitude,
                            fourName=hospitalFour,		
                            fourAddress=hospitalFour_address,
                            fourLatitude=hospitalFour_latitude,
                            fourLongitude=hospitalFour_longitude,
                            fiveName=hospitalFive,		
                            fiveAddress=hospitalFive_address,
                            fiveLatitude=hospitalFive_latitude,
                            fiveLongitude=hospitalFive_longitude
                            )

if __name__ == '__main__':
	app.run(debug = False)

Running the Code

Run the code using any Python IDE like Spyder or PyCharm else simple use command prompt or terminal to execute the code.

reverse_cmd

Copy the address http://127.0.0.1:5000 and paste it in the browser application. 

When clicked on the marker, the details passed in the code will pop up

This concludes our blog on discovering nearby places using Python Flask. Now you have all the ingredients to build your own search application! Stay tuned for more Python tutorial. Meanwhile, keep learning!