2010-05-02 14 views
7

Tratando de abarcar las formas de django y la forma de hacer las cosas de django. Quiero crear un formulario web básico que permita a un usuario ingresar una dirección y tener esa dirección geocodificada y guardada en una base de datos.geocodificando una dirección en el envío del formulario?

creé un modelo Ubicación:

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) 

y definido un formulario:

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

En mi opinión estoy usando form.save() para guardar el formulario. Esto funciona y guarda una dirección en la base de datos.

Creé un módulo para geocodificar una dirección. No estoy seguro de cuál es la forma de hacer las cosas de django, pero supongo que, desde mi punto de vista, antes de guardar el formulario, necesito geocodificar la dirección y configurar el lat y long. ¿Cómo configuro la latitud y la longitud antes de guardar?

Respuesta

8

Puede anular el método de guardar del modelo. Codifico los datos antes de guardar. Esto está usando googleapi, pero se puede modificar en consecuencia.

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

Muchas gracias voy a probar esto y me pondré en contacto contigo. ¿Cuál es tu opinión sobre geocodificar() devolver una tupla u objeto Coordinate en lugar de una cadena? – User

+0

Esa es una gran idea. Sería más limpio empaquetar mejor los datos antes de regresar. En general, me gusta hacer tales cosas. Lo dejé de esta manera debido a cómo refactoreé la ecuación original. Estaba pensando en CSV todo el camino solo porque así es como regresa de Google, pero me gusta cómo estás pensando. Voy a refactorizar esto para devolver un objeto. – digitaldreamer

+0

Actualización para Google Maps API v3 a continuación. –

0

que estoy haciendo lo mismo como esto podría ser tejo están buscando algo similarstrong texto

# 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) 

y mis puntos de vista

#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

actualización para 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

Similar a otras respuestas:

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 
Cuestiones relacionadas