2011-01-29 56 views
8

我有一个Django表单,其中一个字段是TextInput,表示街道地址。在Django/Python中规范化街道地址

我想正常化数据。例如:

>> normalize('420 East 24th St.') 
'420 E. 24th Street' 

>> normalize('221 Amsterdam Av') 
'221 Amsterdam Ave.' 

>> normalize('221 Amsterdam Avenue') 
'221 Amsterdam Ave.' 

或类似的东西。我已经在使用geopy进行地理编码。也许这可能有帮助?

另外:我应该在哪里正常化?在数据库模型中还是在表单字段的clean函数中?

+0

对于哪个国家/地区? – payne 2011-01-29 18:44:29

+0

对不起:美国。特别是纽约市。 – 2011-01-30 00:04:09

回答

4

这样做的最可靠的方法是利用真实的地址验证服务。根据USPS标准(参见Publication 28),它不仅可以标准化(标准化)地址组件,还可以确定地址是真实的。

完全披露:我为SmartyStreets工作,它提供了这样一个service。下面是说明如何通过HTTP GET请求使用我们的服务了一些非常简单的Python代码示例:

https://github.com/smartystreets/LiveAddressSamples/blob/master/python/street-address.py

2

一种选择是使用Geopy查找某人(如Yahoo或Google Maps)的地址,然后该地址将返回与其匹配的地址的完整地址。您可能需要注意退回地址中的公寓号码被截断(例如“221 Amsterdam Av#330”变成“221 AMSTERDAM AVENUE”)。此外,您还将获得用户可能缩写或拼写错误的城市/州/国家/地区信息。

如果存在多个匹配项,您可以提示用户询问他们的地址是哪个。在没有匹配的情况下,您可以让用户知道,并且可能允许保存地址,具体取决于有效地址的重要性以及您对地址查找提供程序的有效性的信任程度。

至于这样做归一化的形式与模式,我不知道是什么做的事情的首选Django的方法是,但我的偏好是在形式,例如:

def clean(self): 
    # check address via some self-defined helper function 
    matches = my_helper_address_matcher(address, city, state, zip) 
    if not matches: 
     raise forms.ValidationError("Your address couldn't be found...") 
    elif len(matches) > 1: 
     # add javascript into error so the user can select 
     # the address that matches? maybe there is a cleaner way to do this 
     raise forms.ValidationError('Did you mean...') 

你可能的情况下,扔在这个模型中查找函数(或一些helpers.py文件)你想重新使用它在其他领域

+1

谨慎的说法,我已经使用了这些服务,而且它们不是非常准确,尤其是在公寓和分区。而且,即使不是不可能,它们也很难用于处理大批量。 – Cerin 2014-05-12 22:17:13

2

这是我怎么会解决这个(没有双关语意):

### models.py ### 

def normalize_address_for_display(address): 

    display_address = string.capwords(address) 

    # Normalize Avenue 
    display_address = re.sub(r'\b(Avenue|Ave.)\b', 'Ave', display_address) 

    # Normalize Street 
    display_address = re.sub(r'\b(Street|St.)\b', 'St', display_address) 

    # ...and other rules... 

    return display_address 

class Store(models.Model): 

    name = models.CharField(max_length=32) 
    address = models.CharField(max_length=64) 
    city = models.CharField(max_length=32) 
    state = models.CharField(max_length=2) 
    zipcode = models.CharField(max_length=5) 

    @property 
    def display_address(self): 
     return normalize_address_for_display(self.address) 

然后我在模板中使用Place.display_address。这使我可以在不修改的情况下将原始用户提交的数据保留在数据库中,并在需要标准化显示版本时仅使用display_address

征求意见/建议。

4

我最近创建了一个street-address Python模块,其StreetAddressFormatter可用于标准化您的地址。