1

我有一个非常简单的 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)

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

4

1 回答 1

2

我不是 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 字符串。下面有一个简单的 hack,可以删除所有非 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)
于 2013-01-20T18:07:44.427 回答