merged schuylers changes; url / maps to search
This commit is contained in:
commit
5165d8a0f3
|
@ -24,16 +24,23 @@ class FeatureSearchManager(models.GeoManager):
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute("""SELECT set_limit(%f)""" % threshold)
|
cursor.execute("""SELECT set_limit(%f)""" % threshold)
|
||||||
|
|
||||||
def overlaps(self, (minx, miny, maxx, maxy), text=None, srid=4326):
|
def find(self, bbox=None, text=None, adm1=None, adm2=None srid=4326):
|
||||||
bbox = Polygon(((minx,miny),(minx,maxy),(maxx,maxy),(maxx,miny),(minx,miny)),srid=srid)
|
qset = self.get_query_set()
|
||||||
if srid != 4326: bbox.transform(4326) # convert to lon/lat
|
if bbox:
|
||||||
qset = models.GeoManager.get_query_set(self).filter(geometry__bboverlaps=bbox)
|
(minx, miny, maxx, maxy) = bbox
|
||||||
|
bbox = Polygon(((minx,miny),(minx,maxy),(maxx,maxy),(maxx,miny),(minx,miny)),srid=srid)
|
||||||
|
if srid != 4326: bbox.transform(4326) # convert to lon/lat
|
||||||
|
qset = qset.filter(geometry__bboverlaps=bbox)
|
||||||
if text:
|
if text:
|
||||||
text = text.replace("'", "''") # escape the '
|
text = text.replace("'", "''") # escape the '
|
||||||
# use the pg_trgm index
|
# use the pg_trgm index
|
||||||
qset = qset.extra(select={"similarity":"similarity(preferred_name, '%s')" % text},
|
qset = qset.extra(select={"similarity":"similarity(preferred_name, '%s')"},
|
||||||
where=["preferred_name %%%% '%s'" % text],
|
select_params=[text],
|
||||||
|
where=["preferred_name %% '%s'"],
|
||||||
|
params=[text],
|
||||||
order_by=["-similarity"])
|
order_by=["-similarity"])
|
||||||
|
if adm1: qset = qset.filter(admin1__exact=adm1)
|
||||||
|
if adm2: qset = qset.filter(admin2__exact=adm2)
|
||||||
return qset
|
return qset
|
||||||
|
|
||||||
class Feature(models.Model):
|
class Feature(models.Model):
|
||||||
|
@ -41,8 +48,8 @@ class Feature(models.Model):
|
||||||
url = models.CharField(max_length=512, unique=True, verbose_name="URI")
|
url = models.CharField(max_length=512, unique=True, verbose_name="URI")
|
||||||
preferred_name = models.CharField(max_length=512)
|
preferred_name = models.CharField(max_length=512)
|
||||||
feature_type = models.ForeignKey("FeatureType", null=True, blank=True)
|
feature_type = models.ForeignKey("FeatureType", null=True, blank=True)
|
||||||
admin1 = models.CharField(max_length=2, blank=True, verbose_name="State")
|
admin1 = models.CharField(max_length=2, blank=True, verbose_name="State", db_index=True)
|
||||||
admin2 = models.CharField(max_length=255, blank=True, verbose_name="County")
|
admin2 = models.CharField(max_length=255, blank=True, verbose_name="County", db_index=True)
|
||||||
geometry = models.GeometryField()
|
geometry = models.GeometryField()
|
||||||
is_primary = models.BooleanField(default=True)
|
is_primary = models.BooleanField(default=True)
|
||||||
time_frame = models.ForeignKey("TimeFrame", null=True, blank=True)
|
time_frame = models.ForeignKey("TimeFrame", null=True, blank=True)
|
||||||
|
@ -57,11 +64,11 @@ class Feature(models.Model):
|
||||||
return self.preferred_name
|
return self.preferred_name
|
||||||
|
|
||||||
def feature_type_name(self):
|
def feature_type_name(self):
|
||||||
return "%s: %s" % (self.feature_type.code, self.feature_type.name,)
|
return self.feature_type.name.title()
|
||||||
feature_type_name.short_description = "Feature Type"
|
feature_type_name.short_description = "Feature Type"
|
||||||
|
|
||||||
def get_geojson(self):
|
def get_geojson(self, srid=4326):
|
||||||
geom = json.loads(self.geometry.transform(3785, True).geojson)
|
geom = json.loads(self.geometry.transform(srid, True).geojson)
|
||||||
|
|
||||||
if self.feature_type is None:
|
if self.feature_type is None:
|
||||||
feature_type = ''
|
feature_type = ''
|
||||||
|
@ -131,6 +138,8 @@ class Feature(models.Model):
|
||||||
LANGUAGE_CHOICES = (
|
LANGUAGE_CHOICES = (
|
||||||
('en', 'English'),
|
('en', 'English'),
|
||||||
('es', 'Spanish'),
|
('es', 'Spanish'),
|
||||||
|
('un', 'Unknown'),
|
||||||
|
('xx', '(code)'),
|
||||||
)
|
)
|
||||||
|
|
||||||
NAME_TYPE_CHOICES = (
|
NAME_TYPE_CHOICES = (
|
||||||
|
@ -138,6 +147,9 @@ NAME_TYPE_CHOICES = (
|
||||||
('official', 'official'),
|
('official', 'official'),
|
||||||
('historic', 'historic'),
|
('historic', 'historic'),
|
||||||
('colloquial', 'colloquial'),
|
('colloquial', 'colloquial'),
|
||||||
|
('icao', 'ICAO code'),
|
||||||
|
('iata', 'IATA code'),
|
||||||
|
('postcode', 'ZIP code'),
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -10,15 +10,31 @@ def search(request):
|
||||||
|
|
||||||
def search_json(request):
|
def search_json(request):
|
||||||
search_term = request.GET.get("search", "")
|
search_term = request.GET.get("search", "")
|
||||||
|
threshold = request.GET.get("threshold", None)
|
||||||
bbox = request.GET.get("bbox", False)
|
bbox = request.GET.get("bbox", False)
|
||||||
if not bbox:
|
country = request.GET.get("adm0", "US") # right now, unused
|
||||||
return render_to_json_response({'error': 'no bbox parameter'})
|
adm1 = request.GET.get("adm1", "")
|
||||||
|
adm2 = request.GET.get("adm2", "")
|
||||||
bs = bbox.split(",")
|
srid = int(request.GET.get("srid", 4326))
|
||||||
bs_param = (float(bs[0]), float(bs[1]), float(bs[2]), float(bs[3]),)
|
|
||||||
|
|
||||||
features_qset = Feature.search.overlaps(bs_param, text=search_term, srid=3785)[0:20]
|
if threshold:
|
||||||
features = [f.get_geojson() for f in features_qset]
|
try:
|
||||||
|
threshold = float(threshold)
|
||||||
|
except ValueError:
|
||||||
|
return render_to_json_response({'error': 'threshold must be a float'})
|
||||||
|
|
||||||
|
if bbox:
|
||||||
|
try:
|
||||||
|
bbox = map(float, bbox.split(","))
|
||||||
|
except ValueError:
|
||||||
|
bbox = None
|
||||||
|
return render_to_json_response({'error': 'bbox must be in the form: minx,miny,maxx,maxy'})
|
||||||
|
|
||||||
|
if not bbox and not search_term:
|
||||||
|
return render_to_json_response({'error': 'must supply either a valid `bbox` or a `search` parameter'})
|
||||||
|
|
||||||
|
features_qset = Feature.search.find(bbox=bbox, text=search_term, threshold=threshold, adm1=adm1, adm2=adm2, srid=srid)[0:20]
|
||||||
|
features = [f.get_geojson(srid) for f in features_qset]
|
||||||
d = {
|
d = {
|
||||||
'type': 'FeatureCollection',
|
'type': 'FeatureCollection',
|
||||||
'features': features
|
'features': features
|
||||||
|
|
|
@ -9,6 +9,7 @@ admin.autodiscover()
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
# Example:
|
# Example:
|
||||||
# (r'^gazetteer/', include('gazetteer.foo.urls')),
|
# (r'^gazetteer/', include('gazetteer.foo.urls')),
|
||||||
|
(r'^$', 'places.views.search'),
|
||||||
('^search$', 'places.views.search'),
|
('^search$', 'places.views.search'),
|
||||||
('^feature/search.json$', 'places.views.search_json'),
|
('^feature/search.json$', 'places.views.search_json'),
|
||||||
('^search_related$', 'places.views.search_related'),
|
('^search_related$', 'places.views.search_related'),
|
||||||
|
@ -19,6 +20,7 @@ urlpatterns = patterns('',
|
||||||
(r'^ajax_select/', include('ajax_select.urls')),
|
(r'^ajax_select/', include('ajax_select.urls')),
|
||||||
# Uncomment the next line to enable the admin:
|
# Uncomment the next line to enable the admin:
|
||||||
(r'^admin/', include(admin.site.urls)),
|
(r'^admin/', include(admin.site.urls)),
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if settings.LOCAL_DEVELOPMENT:
|
if settings.LOCAL_DEVELOPMENT:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user