Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Geopy ValueError "Didn't find exactly one match" when geocoding

In Django, I have been trying to get a search field to geocode a location and spit out a list from my db sorted by distance. So far everything works except when I search for a location that Google returns multiple results form such as "ann arbor, MI". I get the ValueError "Didn't find exactly one placemark! (Found 2.)" Here is my views.py

from django.shortcuts import render_to_response
from models import CampSite
from geopy import geocoders
from django.contrib.gis.geos import *
from django.contrib.gis.measure import D
from campsites.forms import SearchForm
from django.http import HttpResponseRedirect


def results(request):
    query = request.GET['q']
    g = geocoders.Google(resource='maps')
    location, (lat, lon) = g.geocode(query) 
    pnt = fromstr("POINT(%s %s)" % (lon, lat))
    distance_from_point = {'mi':'2000'}
    results = CampSite.objects.filter(lonlat__distance_lte=(pnt,D(**distance_from_point))).distance(pnt).order_by('distance')
    return render_to_response('results.html',{'location': location, 'lat': lat, 'lon': lon, 'results':results})

The common solution I found online was to change

location, (lat, lon) = g.geocode(query)


to


location, (lat, lon) = g.geocode(query, exactly_one=False)

However, this produced the new ValueError "String or unicode input unrecognized as WKT EWKT, and HEXEWKB."

This is my first django project I'm doing outside of tutorials, so thankyou for being gentile.

like image 998
bcoop713 Avatar asked Sep 20 '12 18:09

bcoop713


1 Answers

In Python, the interpreter is your best friend.

>>> g.geocode('ann arbor, MI', exactly_one=False)
[(u'Ann Arbor, MI, USA', (42.2808256, -83.743037799999996)),
 (u'Ann Arbor, MI, USA', (42.307649300000001, -83.8473015))]

If you try your code snippet, you will realize that when used with exactly_one=False, the method returns a list of tuples, not a single tuple - so your code need to be refactored accordingly.

results = []
geocodes = g.geocode(query, exactly_one=False)
for geocode in geocodes:
    location, (lat, lon) = geocode
    pnt = fromstr("POINT(%s %s)" % (lon, lat))
    distance_from_point = {'mi':'2000'}
    results.append(
        CampSite.objects.filter(
             lonlat__distance_lte=(
                  pnt,
                  D(**distance_from_point)
             )
        ).distance(pnt).order_by('distance')
    )

The above is untested, but the after the loop you should end up with a list of results. Then you should decide what to do:

  • show just the first (geocodes[0], results[0])
  • ask the user to choose from the list
  • show all results (iterate over zip(geocodes, results) in the template)
like image 157
Paulo Scardine Avatar answered Nov 05 '22 07:11

Paulo Scardine