代码之家  ›  专栏  ›  技术社区  ›  User

在表单提交时对地址进行地理编码?

  •  7
  • User  · 技术社区  · 14 年前

    试着用django的形式和django做事的方式来表达我的想法。我想创建一个基本的web表单,允许用户输入一个地址,并对该地址进行地理编码并保存到数据库中。

    我创建了一个位置模型:

    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)
    

    定义了一种形式:

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

    在我看来我在用 form.save() 以保存表单。这样可以工作并将地址保存到数据库。

    我创建了一个模块来对地址进行地理编码。我不知道Django的工作方式是什么,但我想在我看来,在保存表单之前,我需要对地址进行地理编码并设置纬度和经度。保存前如何设置经纬度?

    5 回复  |  直到 9 年前
        1
  •  8
  •   digitaldreamer    14 年前

    可以重写模型的保存方法。我在保存之前对数据进行地理编码。这是使用GoogleAPI,但可以相应地进行修改。

    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 ','
    
        2
  •  3
  •   Ryan Allen bradley.ayers    9 年前

    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)
    
        3
  •  1
  •   Bernhard Vallant    14 年前

    你也可以使用 django.db.models.signals.pre_save -信号!

    查看django的信号文档 http://docs.djangoproject.com/en/dev/topics/signals/ .

        4
  •  0
  •   MajorGeek    14 年前

    我也是这样做的 可能是紫杉在找类似的文字

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

    以及我的观点

        #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}) 
    
        5
  •  0
  •   MatheusJardimB A B    10 年前

    类似于其他答案:

    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