2010-05-02 5 views
7

Cercando di abbracciare le forme del django e il modo di fare django. Voglio creare un modulo Web di base che consenta a un utente di inserire un indirizzo e avere quell'indirizzo geocodificato e salvato in un database.Geocodifica un indirizzo nell'invio del modulo?

ho creato un modello Località:

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) 

e definito una forma:

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

A mio avviso sto usando form.save() per salvare il modulo. Funziona e salva un indirizzo nel database.

Ho creato un modulo per geocodificare un indirizzo. Non sono sicuro di quale sia il modo di fare django per fare le cose, ma suppongo che, a mio avviso, prima di salvare il modulo, devo geocodificare l'indirizzo e impostare lat e long. Come posso impostare la latitudine e la longitudine prima di salvare?

risposta

8

È possibile sovrascrivere il metodo di salvataggio del modello. Ho geocodificare i dati prima di salvare. Questo sta usando googleapi, ma può essere modificato di conseguenza.

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 ',' 
+0

Grazie mille, proverò e tornerò da te. Cosa ne pensi di geocode() restituendo una tupla o un oggetto Coordinate invece di una stringa? – User

+0

Questa è una grande idea. Sarebbe più pulito impacchettare meglio i dati prima di tornare. In generale mi piace fare cose del genere. L'ho lasciato in questo modo a causa di come ho rifattorizzato l'equazione originale. Stavo pensando che CSV è tutto solo perché è così che torna da google, ma mi piace come stai pensando. Ho intenzione di refactoring questo per restituire un oggetto. – digitaldreamer

+0

Aggiornamento per l'API di Google Maps v3 di seguito. –

0

sto facendo la stessa cosa come questa potrebbe essere tasso sono alla ricerca di qualcosa di similarstrong testo

# forms.py 
from django.contrib.gis.utils import GeoIP 


class registerForm(forms.ModelForm): 
class Meta: 
    model=register 
    fields = ('Availability', 'Status') 

def save(self,ip_address, *args, **kwargs): 
    g = GeoIP() 
    lat, lon = g.lat_lon(ip_address) 
    user_location = super(registerForm, self).save(commit=False) 
    user_location.latitude = lat 
    user_location.longitude = lon 
    user_location.save(*args, **kwargs) 

e le mie opinioni

#views.py 
    if request.method == "POST": 
ip_address=request.META['REMOTE_ADDR'] 
    rform = registerForm(data = request.POST) 
    if rform.is_valid(): 
    register = rform.save(commit=False) 
    register.user=request.user 
    register.save(ip_address) 
     return render_to_response('home.html') 
else: 
    rform = registerForm() 
return render_to_response('status_set.html',{'rform':rform}) 
3

aggiornamento per 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) 
0

simile ad altre risposte:

def geocode(address, city, state, zip_code): 
    try: 
     location_param = urllib.request.quote("%s, %s, %s, %s" % (address, city, state, zip_code)) 
     url_request = "http://maps.googleapis.com/maps/api/geocode/json?address=%s&sensor=false" % location_param 
     result = requests.get(url_request) 
     data = result.json() 
     location = data['results'][0]['geometry']['location'] 
     lat = location['lat'] 
     lng = location['lng'] 
     return lat, lng 
    except Exception: 
     return None