2011-01-29 15 views
8

Mam formularz Django, w którym jedno z pól to TextInput dla adresu ulicy.Normalizowanie adresów ulic w Django/Pythonie

Chcę znormalizować dane. Na przykład:

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

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

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

Albo coś w tym stylu. Używam już geokodowania geopy. Być może to może pomóc?

Również: Gdzie powinienem normalizować? W modelu bazy danych lub w funkcji czyszczenia pola formularza?

+0

Dla jakiego kraju/krajów? – payne

+0

Przepraszamy: USA. W szczególności NYC. –

Odpowiedz

4

Najbardziej niezawodnym sposobem na to jest skorzystanie z usługi weryfikacji adresu w dobrej wierze. Nie tylko ustandaryzuje (znormalizuje) komponenty adresów zgodnie ze standardami USPS (patrz: Publication 28), ale będziesz także pewien, że adres jest prawdziwy.

Pełne ujawnienie: Pracuję dla SmartyStreets, która zapewnia właśnie taką service. Oto niektóre naprawdę proste Pythona przykładowy kod, który pokazuje, jak korzystać z naszych usług za pośrednictwem żądanie HTTP GET:

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

+0

Pracuję nad biblioteką, która musi zajmować się adresami, a chociaż SmartyStreets wygląda trochę drogo (chociaż darmowy poziom jest dość hojny) i prawdopodobnie dodawałby trochę opóźnień do mojej biblioteki (wymagającej podróży w obie strony do serwer), wygląda na całkiem niesamowitą usługę. Myślę, że mogę dodać do niego wsparcie. * Kontynuuj dobrą pracę! * – bgw

+0

Dzięki! Wiemy, że jesteśmy geograficznie rozproszeni i żądania są przetwarzane w centrum danych najbliżej lokalizacji użytkownika, co zmniejsza opóźnienie. – mdwhatcott

2

Jedną opcją jest użycie Geopy do wyszukania adresu na kimś takim jak Yahoo lub Google Maps, który zwróci pełny adres tych, z którymi są one zgodne. Być może będziesz musiał uważać na obcięcie numerów mieszkań w zwróconym adresie (np. "221 Amsterdam Av # 330" staje się "221 AMSTERDAM AVENUE"). Ponadto otrzymasz również informacje o mieście/stanie/kraju, które użytkownik mógł również skrócić lub wprowadzić błędnie.

W przypadku wielu dopasowań można poprosić użytkownika o opinię na temat jego adresu. W przypadku braku dopasowań, możesz również poinformować użytkownika i ewentualnie zezwolić na zapisanie adresu w każdym razie, w zależności od tego, jak ważny jest poprawny adres i jak wiele zaufania przypisujesz do ważności dostawcy wyszukiwania adresu.

Odnośnie robi to normalizację w postaci vs. modelu, nie wiem co preferowanym Django sposób robienia rzeczy jest, ale moje preferencje jest w postaci, na przykład:

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...') 

Ty mogłyby rzucić tę funkcję odnośnika w modelu (lub jakiś plik helpers.py) w przypadku, gdy chcesz używać go w innych dziedzinach

+1

Ostrożnie, korzystałem z tych usług i nie są one bardzo dokładne, szczególnie w przypadku apartamentów i lokali. Ponadto są one bardzo trudne, jeśli nie niemożliwe, do przetwarzania dużych partii. – Cerin

2

ten sposób skończyło się rozwiązania tego (gra słów nie przeznaczonych):

### 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) 

Następnie używam Place.display_address w szablonach. To pozwala mi zachować oryginalne dane przesłane przez użytkownika w bazie danych bez modyfikacji i po prostu użyć display_address, kiedy chcę znormalizowaną wersję wyświetlacza.

Otwórz dla komentarzy/sugestii.

4

Niedawno stworzył moduł street-address Pythona, a jego StreetAddressFormatter mogą być stosowane do normalizacji swój adres.