Django形成地理编码 - 在哪里进行地理编码,如何验证,如何传递地理编码结果

时间:2013-01-20 17:17:17

标签: django forms validation geocode

我有一个非常简单的Django表单,它由一个字段组成 - “地址”:

class AddressSearchForm(forms.Form):
    """
        A form that allows a user to enter an address to be geocoded
    """
    address = forms.CharField()

我可能甚至不需要使用表单,因为我没有保存这些数据 - 我只是将它收集起来用于搜索。但是,我想执行验证:

def clean_address():
    data = self.cleaned_data
    g = geocoders.Google()
    try:
        place, (lat,lng) = g.geocode(data['address'])
    except (GQueryError):
        raise forms.ValidationError('Please enter a valid address')
    except (GeocoderResultError, GBadKeyError, GTooManyQueriesError):
        raise forms.ValidationError('There was an error geocoding your address. Please      try again')
    except:
        raise forms.ValidationError('An unknown error occured. Please try again')

此外,我想使用此地理编码结果将Point对象传递给我的视图:

from django.contrib.gis.geos import Point
point = Point(lng, lat)

我的问题是,如何将地址和点数据传递给我的视图?我可以只传递地址然后在视图中重新编码,但那将是重复的代码。那么,如何从表单中传递点对象?我应该使用隐藏的字段吗?其他建议?提前谢谢。

1 个答案:

答案 0 :(得分:1)

我不是django专家,但这就是我所做的:

 def clean_homeaddress(self):
        in_address = self.cleaned_data['homeaddress']        
        place, self.cleaned_data['homelocation'] = address_to_latlng(in_address, True)
        return place
哦,顺便说一句,看看下面的包装器。 geocoders.Google无法正确处理unicode字符串。下面有一个简单的黑客删除所有非ascii字符。我还没有时间找出更好的解决方案。

def address_to_latlng(address, return_address = False):
    """ returns GoeDjango POINT string value for given location (address)
        if return_address is true, it'll return 2-tuple: (address, point)
        otherwise it returns point
    """ 
    g = geocoders.Google()
    try:
        #TODO: not really replace, geocode should use unicode strings
        address = address.encode('ascii', 'replace')            
        place, latlng = g.geocode(address)            
    except Exception as e:            
        raise ValidationError(_(u"Incorrect location provided"))
    point = 'POINT(%f %f)' % tuple(reversed(latlng))
    if return_address:
        return (place, point)    
    return point

根据要求,有完整的代码。这个会将位置打印到输出控制台,它会在会话中保留“已清理”(由Google返回)地址,以便在每次显示表单时将其显示给用户。

class GeoForm(forms.Form):
    address = forms.CharField()    

    def clean_address(self):
        in_address = self.cleaned_data['address']        
        place, self.cleaned_data['location'] = address_to_latlng(in_address, True)
        return place

class GeoView(FormView):
    form_class = GeoForm
    template_name = 'geoview.html'
    success_url = '/sandbox/geo'
    def get_initial(self):
        if '_address' in self.request.session:
            return {'address': self.request.session['_address']}
        return {}
    def form_valid(self,form):
        print form.cleaned_data['location']
        self.request.session['_address'] = form.cleaned_data['address']
        return super(GeoView, self).form_valid(form)