2011-01-29 55 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可用於標準化您的地址。