python django django-models django-forms geopy

Normalizar direcciones de calles en Django/Python



django-models django-forms (4)

Tengo un formulario de Django donde uno de los campos es un TextInput para una dirección de calle.

Quiero normalizar los datos. Por ejemplo:

>> normalize(''420 East 24th St.'') ''420 E. 24th Street'' >> normalize(''221 Amsterdam Av'') ''221 Amsterdam Ave.'' >> normalize(''221 Amsterdam Avenue'') ''221 Amsterdam Ave.''

O algo así. Ya estoy usando geopy para geocodificar. Tal vez esto podría ayudar?

Además: ¿Dónde debería normalizar? En el modelo de base de datos o en la función de limpieza del campo de formulario?


Una opción sería usar Geopy para buscar la dirección en alguien como Yahoo o Google Maps, que luego devolverá la dirección completa de la (s) persona (s) con la que coinciden. Es posible que tenga que vigilar para ver si los números de apartamento se truncan en la dirección devuelta (por ejemplo, "221 Amsterdam Av # 330" que se convierte en "221 AMSTERDAM AVENUE"). Además, también obtendrá la información de la ciudad / estado / país, que el usuario también puede haber abreviado o mal escrito.

En el caso de que haya múltiples coincidencias, puede solicitar al usuario retroalimentación sobre cuál es su dirección. En el caso de que no haya coincidencias, también puede informar al usuario, y posiblemente permitir que la dirección se guarde de todos modos, dependiendo de la importancia de una dirección válida y de la confianza que deposite en la validez de los proveedores de búsqueda de direcciones.

En cuanto a hacer esta normalización en la forma vs. modelo, no sé cuál es la forma preferida de hacer las cosas de Django, pero mi preferencia está en la forma, por ejemplo:

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

Puede lanzar esta función de búsqueda en el modelo (o en algún archivo helpers.py) en caso de que quiera reutilizarlo en otras áreas


Así es como terminé abordando esto (sin juego de palabras):

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

Luego uso Place.display_address en las plantillas. Esto me permite mantener los datos enviados por el usuario original en la base de datos sin modificaciones y solo uso display_address cuando quiero una versión de visualización normalizada.

Abierto para comentarios / sugerencias.


La forma más confiable de hacerlo es utilizar un servicio de verificación de dirección de buena fe. No solo estandarizará (normalizará) los componentes de la dirección según los estándares de USPS (consulte la Publicación 28 ), sino que también estará seguro de que la dirección es real.

Divulgación completa: trabajo para SmartyStreets, que brinda exactamente ese servicio . Aquí hay un código de muestra de Python realmente simple que muestra cómo usar nuestro servicio a través de una solicitud HTTP GET:

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


Recientemente he creado un módulo python de dirección de calle , y su StreetAddressFormatter se puede utilizar para normalizar su dirección.