Нормализация уличных адресов в Django / Python - PullRequest
8 голосов
/ 29 января 2011

У меня есть форма Django, где одним из полей является TextInput для адреса улицы.

Я хочу нормализовать данные.Например:

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

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

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

или что-то в этом роде.Я уже использую geopy для геокодирования.Возможно, это могло бы помочь?

Также: Где я должен нормализовать?В модели базы данных или в чистой функции поля формы?

Ответы [ 4 ]

4 голосов
/ 27 ноября 2012

Недавно я создал модуль Python street-address , и его StreetAddressFormatter можно использовать для нормализации вашего адреса.

4 голосов
/ 26 октября 2011

Самый надежный способ сделать это - использовать службу проверки подлинного адреса. Он не только стандартизирует (нормализует) компоненты адреса в соответствии со стандартами USPS (см. Публикация 28 ), но вы также будете уверены, что адрес реальный.

Полное раскрытие: я работаю на SmartyStreets, которая предоставляет именно такую ​​ услугу . Вот несколько действительно простых примеров кода Python, которые показывают, как использовать наш сервис через HTTP-запрос GET:

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

3 голосов
/ 07 февраля 2011

Вот так я и решил (не каламбур):

### 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, когда я хочу нормализованную версию дисплея.

Открыто для комментариев / предложений.

2 голосов
/ 29 января 2011

Одним из вариантов может быть использование 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) на случай, если вы захотите использовать ее в других областях

...