【问题标题】:Django form geocoding - where to geocode, how to validate, how to pass geocode resultDjango 表单地理编码 - 在哪里进行地理编码,如何验证,如何传递地理编码结果
【发布时间】:2013-01-20 17:17:16
【问题描述】:

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

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

【问题讨论】:

    标签: django forms validation geocode


    【解决方案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 字符串。下面有一个简单的 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)
    

    【讨论】:

    • 谢谢。你的表格是什么样的?您如何同时传递家庭地址和家庭位置?
    • 另外,您如何在视图中访问这些数据?
    • 而且,对于 Django Point 字符串,经度不应该放在第一位吗?
    • 表单只包含 homeaddress 字符域,因为我没有理由显示用户 POINT 数据(homelocation 值)。我正在使用 form.cleaned_data['homelocation'] 在视图中访问它......考虑到点,你是绝对正确的。这个后来修复了,我只是打开了错误的文件副本。
    • 您使用的是基于类的视图吗?您是否使用位置数据进行查询?你介意分享你的视图代码吗?我在试图弄清楚在这种情况下表单和视图如何交互时遇到了很多麻烦。谢谢!
    猜你喜欢
    • 2010-11-02
    • 1970-01-01
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    相关资源
    最近更新 更多