views:

298

answers:

2

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?

+1  A: 

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 ','
digitaldreamer
Great thanks I will try this out and get back to you. What's your take on geocode() returning a tuple or Coordinate object instead of a string?
User
That's a great idea. It would be cleaner to package the data better before returning. Generally I like to do such things. I left it this way because of how I refactored the original equation. I was thinking CSV's the whole way just because that's how it comes back from google, but I like how you're thinking. I'm going to refactor this to return an object.
digitaldreamer
A: 

You could also use the django.db.models.signals.pre_save-signal!

Have a look at Django's signal documentation at http://docs.djangoproject.com/en/dev/topics/signals/.

lazerscience