Нормализация уличных адресов в Django/Python

у меня есть форма 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 ответов


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

полное раскрытие информации: я работаю на SmartyStreets, которая предоставляет именно такой сервис. Вот очень простой пример кода python, который показывает, как использовать наш сервис через HTTP GET запрос:

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


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


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


вот как я закончил, обращаясь к этому (без каламбура):

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

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