Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Geocoding an address on form submission?

Trying to wrap my head around django forms and the django way of doing things. I want to create a basic web form that allows a user to input an address and have that address geocoded and saved to a database.

I created a Location model:

class Location(models.Model):
    address = models.CharField(max_length=200)
    city = models.CharField(max_length=100)
    state = models.CharField(max_length=100, null=True)
    postal_code = models.CharField(max_length=100, null=True)
    country = models.CharField(max_length=100)
    latitude = models.DecimalField(max_digits=18, decimal_places=10, null=True)
    longitude = models.DecimalField(max_digits=18, decimal_places=10, null=True)

And defined a form:

class LocationForm(forms.ModelForm):
    class Meta:
        model = models.Location
        exclude = ('latitude','longitude')

In my view I'm using form.save() to save the form. This works and saves an address to the database.

I created a module to geocode an address. I'm not sure what the django way of doing things is, but I guess in my view, before I save the form, I need to geocode the address and set the lat and long. How do I set the latitude and longitude before saving?

like image 361
User Avatar asked May 02 '10 21:05

User


People also ask

What is geocoding an address?

Geocoding is the process of converting addresses (like a street address) into geographic coordinates (latitude and longitude), which you can use to place markers on a map, or position the map. The focus of this document is to clarify considerations involved when geocoding addresses.

How do I find the geocode for an address?

One way to find your geolocation is to simply perform a lookup online. Melissa's Geocoder Lookup tool returns latitude, longitude, county, census tract and block data based on an address or ZIP Code. Simply enter the address or ZIP Code into the easy-to-use Lookups interface and submit.


2 Answers

You can override the model's save method. I geocode the data before saving. This is using googleapi, but it can be modified accordingly.

import urllib

def save(self):
    location = "%s, %s, %s, %s" % (self.address, self.city, self.state, self.zip)

    if not self.latitude or not self.longitude:
        latlng = self.geocode(location)
        latlng = latlng.split(',')
        self.latitude = latlng[0]
        self.longitude = latlng[1]

    super(Marker, self).save()

def geocode(self, location):
    output = "csv"
    location = urllib.quote_plus(location)
    request = "http://maps.google.com/maps/geo?q=%s&output=%s&key=%s" % (location, output, settings.GOOGLE_API_KEY)
    data = urllib.urlopen(request).read()
    dlist = data.split(',')
    if dlist[0] == '200':
        return "%s,%s" % (dlist[2], dlist[3])
    else:
        return ','
like image 85
digitaldreamer Avatar answered Oct 26 '22 01:10

digitaldreamer


Update for Google Maps API v3:

import json
import urllib.parse
from decimal import Decimal

def save(self):
    if not self.lat or not self.lng:
        self.lat, self.lng = self.geocode(self.address)

    super(Location, self).save()

def geocode(self, address):
    address = urllib.parse.quote_plus(address)
    maps_api_url = "?".join([
        "http://maps.googleapis.com/maps/api/geocode/json",
        urllib.parse.urlencode({"address": address, "sensor": False})
    ])
    response = urllib.urlopen(maps_api_url)
    data = json.loads(response.read().decode('utf8'))

    if data['status'] == 'OK':
        lat = data['results'][0]['geometry']['location']['lat']
        lng = data['results'][0]['geometry']['location']['lng']
        return Decimal(lat), Decimal(lng)
like image 29
Ryan Allen Avatar answered Oct 25 '22 23:10

Ryan Allen