Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 21 additions & 13 deletions ebpub/ebpub/db/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,34 +384,42 @@ def search(request, schema_slug=''):
exc_info=True)
else:
if result['ambiguous']:
if result['type'] == 'block':
if result['type'] == 'block' or result['type'] == 'address':
streets = []
street_blocks = {}
for block in result['result']:
street_name = block.street_pretty_name
choices = {}
for x in result['result']:
block = x if result['type'] == 'block' else x['block']
street_name = '{0}, {1}, {2} {3}'.format(block.street_pretty_name,
block.city.title(), block.state, block.zip).strip()
if street_name not in streets:
streets.append(street_name)
street_blocks[street_name] = []
street_blocks[street_name].append(block)

choices = [{'name': s, 'blocks': street_blocks[s]} for s in streets]
choices[street_name] = {'name': street_name, 'street_url': block.street_url, 'blocks': []}
choices[street_name]['blocks'].append(block)
choices = choices.values()
for choice in choices:
choice['blocks'].sort(key=lambda x: (x.predir, x.postdir, x.from_num))
return eb_render(request, 'db/search_invalid_block.html', {
'query': q,
'choices': choices,
})
else:
else: # 'location' or 'place'
# TODO: does this work with Places?
return eb_render(request, 'db/did_you_mean.html', {'query': q, 'choices': result['result']})

elif result['type'] == 'location':
return HttpResponseRedirect(url_prefix + getattr(result['result'], url_method)())
elif result['type'] == 'place':
block, distance = geocoder.reverse.reverse_geocode(result['result'].location)
return HttpResponseRedirect(url_prefix + getattr(block, url_method)())

# The current Place search implementation is error-prone & should be revisited.
# elif result['type'] == 'place':
# block, distance = geocoder.reverse.reverse_geocode(result['result'].location)
# return HttpResponseRedirect(url_prefix + getattr(block, url_method)())

elif result['type'] == 'address':
# Block
if result['result']['block']:
return HttpResponseRedirect(url_prefix + getattr(result['result']['block'], url_method)())
url = getattr(result['result']['block'], url_method)()
if url:
return HttpResponseRedirect(url_prefix + url)
# Intersection
try:
intersection = Intersection.objects.get(id=result['result']['intersection_id'])
Expand Down
81 changes: 46 additions & 35 deletions ebpub/ebpub/geocoder/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q
from ebpub.geocoder.parser.parsing import normalize, parse, ParsingError
from ebpub.metros.allmetros import get_metro
from ebpub.utils.text import address_to_block
import logging
import re
Expand Down Expand Up @@ -161,7 +162,7 @@ def geocode(self, location):
# If multiple results were found, check whether they have the
# same point. If they all have the same point, don't raise the
# AmbiguousResult exception -- just return the first one.
#
#
# An edge case is if result['point'] is None. This could happen
# if the geocoder found locations, not points. In that case,
# just raise the AmbiguousResult.
Expand Down Expand Up @@ -268,24 +269,33 @@ def _db_lookup(self, location):
the DB. Always returns a list of Address dictionaries (or an empty list
if no results are found).
"""
if not location['number']:
return []
# if not location['number']:
# return []

# Query the blocks database.
try:
# Defer this to avoid import cycle.
from ebpub.streets.models import Block
blocks = Block.objects.search(
street=location['street'],
number=location['number'],
predir=location['pre_dir'],
prefix=location['prefix'],
suffix=location['suffix'],
postdir=location['post_dir'],
city=location['city'],
state=location['state'],
zipcode=location['zip'],
)
from ebpub.db.models import Location

# Also searches in cities with matching normalized name.
city_type_slug = get_metro()['city_location_type']
cities = [location['city']] + list(Location.objects.filter(location_type__slug=city_type_slug,
normalized_name=location['city']).values_list('name', flat=True))
blocks = []
for city in cities:
blocks.extend(Block.objects.search(
street=location['street'],
number=location['number'],
predir=location['pre_dir'],
prefix=location['prefix'],
suffix=location['suffix'],
postdir=location['post_dir'],
city=city,
state=location['state'],
zipcode=location['zip'],
))
blocks = set(blocks)
except:
# TODO: replace with Block-specific exception?
raise
Expand Down Expand Up @@ -469,27 +479,28 @@ def full_geocode(query, search_places=True, convert_to_block=True, guess=False,
from ebpub.streets.models import Place, PlaceSynonym

# Search the Location table.
try:
canonical_loc = LocationSynonym.objects.get_canonical(query)
loc = Location.objects.get(normalized_name=canonical_loc)
except Location.DoesNotExist:
pass
else:
logger.debug('geocoded %r to Location %s' % (query, loc))
return {'type': 'location', 'result': loc, 'ambiguous': False}

# Search the Place table, for stuff like "Sears Tower".
if search_places:
canonical_place = PlaceSynonym.objects.get_canonical(query)
places = Place.objects.filter(normalized_name=canonical_place)
if len(places) == 1:
logger.debug(u'geocoded %r to Place %s' % (query, places[0]))
return {'type': 'place', 'result': places[0], 'ambiguous': False}
elif len(places) > 1:
# TODO: Places don't know about city, state, zip...
# so we can't disambiguate.
logger.debug(u'geocoded %r to multiple Places: %s' % (query, unicode(places)))
return {'type': 'place', 'result': places, 'ambiguous': True}
canonical_loc = LocationSynonym.objects.get_canonical(query)
locs = Location.objects.filter(normalized_name=canonical_loc)
if len(locs) == 1:
logger.debug(u'geocoded %r to Location %s' % (query, locs[0]))
return {'type': 'location', 'result': locs[0], 'ambiguous': False}
elif len(locs) > 1:
logger.debug(u'geocoded %r to multiple Locations: %s' % (query, unicode(locs)))
return {'type': 'location', 'result': locs, 'ambiguous': True}

# The current Place search implementation is error-prone & should be revisited.
# # Search the Place table, for stuff like "Sears Tower".
# if search_places:
# canonical_place = PlaceSynonym.objects.get_canonical(query)
# places = Place.objects.filter(normalized_name=canonical_place)
# if len(places) == 1:
# logger.debug(u'geocoded %r to Place %s' % (query, places[0]))
# return {'type': 'place', 'result': places[0], 'ambiguous': False}
# elif len(places) > 1:
# # TODO: Places don't know about city, state, zip...
# # so we can't disambiguate.
# logger.debug(u'geocoded %r to multiple Places: %s' % (query, unicode(places)))
# return {'type': 'place', 'result': places, 'ambiguous': True}

# Try geocoding this as an address.
geocoder = SmartGeocoder(use_cache=getattr(settings, 'EBPUB_CACHE_GEOCODER', False))
Expand Down