Moving the spatial query. You can enable it loading the spatial_query plugin in the ini file.
This commit is contained in:
parent
76183b6f23
commit
1710205cf9
|
@ -0,0 +1,6 @@
|
|||
try:
|
||||
import pkg_resources
|
||||
pkg_resources.declare_namespace(__name__)
|
||||
except ImportError:
|
||||
import pkgutil
|
||||
__path__ = pkgutil.extend_path(__path__, __name__)
|
|
@ -0,0 +1,63 @@
|
|||
import sys
|
||||
import re
|
||||
from pprint import pprint
|
||||
|
||||
from ckan.lib.cli import CkanCommand
|
||||
from ckanext.spatial.lib import save_extent
|
||||
|
||||
class Extents(CkanCommand):
|
||||
'''Creates or updates pacakge extents.
|
||||
Creates or updates the extent geometry column for packages with
|
||||
a bounding box defined in extras
|
||||
|
||||
Usage:
|
||||
|
||||
extents update
|
||||
|
||||
The commands should be run from the ckanext-spatial directory and expect
|
||||
a development.ini file to be present. Most of the time you will
|
||||
specify the config explicitly though::
|
||||
|
||||
paster extents update --config=../ckan/development.ini
|
||||
|
||||
'''
|
||||
|
||||
summary = __doc__.split('\n')[0]
|
||||
usage = __doc__
|
||||
max_args = 1
|
||||
min_args = 0
|
||||
|
||||
def command(self):
|
||||
self._load_config()
|
||||
print ''
|
||||
|
||||
if len(self.args) == 0:
|
||||
self.parser.print_usage()
|
||||
sys.exit(1)
|
||||
cmd = self.args[0]
|
||||
if cmd == 'update':
|
||||
self.update_extents()
|
||||
else:
|
||||
print 'Command %s not recognized' % cmd
|
||||
|
||||
def update_extents(self):
|
||||
from ckan.model import PackageExtra, Package, Session
|
||||
conn = Session.connection()
|
||||
packages = [extra.package \
|
||||
for extra in \
|
||||
Session.query(PackageExtra).filter(PackageExtra.key == 'bbox-east-long').all()]
|
||||
|
||||
error = False
|
||||
for package in packages:
|
||||
try:
|
||||
save_extent(package)
|
||||
except:
|
||||
errors = True
|
||||
|
||||
if error:
|
||||
msg = "There was an error saving the package extent. Have you set up the package_extent table in the DB?"
|
||||
else:
|
||||
msg = "Done. Extents generated for %i packages" % len(packages)
|
||||
|
||||
print msg
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
from ckan.lib.helpers import json
|
||||
import ckan.lib.helpers as h
|
||||
from ckan.lib.base import c, g, request, \
|
||||
response, session, render, config, abort, redirect
|
||||
from ckan.controllers.rest import BaseApiController
|
||||
|
||||
from ckan.model import Session
|
||||
|
||||
from ckanext.spatial.lib import get_srid
|
||||
|
||||
|
||||
class ApiController(BaseApiController):
|
||||
|
||||
db_srid = int(config.get('ckan.spatial.srid', '4258'))
|
||||
|
||||
def spatial_query(self):
|
||||
if not 'bbox' in request.params:
|
||||
abort(400)
|
||||
|
||||
bbox = request.params['bbox'].split(',')
|
||||
if len(bbox) is not 4:
|
||||
abort(400)
|
||||
|
||||
minx = float(bbox[0])
|
||||
miny = float(bbox[1])
|
||||
maxx = float(bbox[2])
|
||||
maxy = float(bbox[3])
|
||||
|
||||
params = {'minx':minx,'miny':miny,'maxx':maxx,'maxy':maxy,'db_srid':self.db_srid}
|
||||
|
||||
srid = get_srid(request.params.get('crs')) if 'crs' in request.params else None
|
||||
if srid and srid != self.db_srid:
|
||||
# The input bounding box is defined in another projection, we need
|
||||
# to transform it
|
||||
statement = """SELECT package_id FROM package_extent WHERE
|
||||
ST_Intersects(
|
||||
ST_Transform(
|
||||
ST_GeomFromText('POLYGON ((%(minx)s %(miny)s,
|
||||
%(maxx)s %(miny)s,
|
||||
%(maxx)s %(maxy)s,
|
||||
%(minx)s %(maxy)s,
|
||||
%(minx)s %(miny)s))',%(srid)s),
|
||||
%(db_srid)s)
|
||||
,the_geom)"""
|
||||
params.update({'srid': srid})
|
||||
else:
|
||||
statement = """SELECT package_id FROM package_extent WHERE
|
||||
ST_Intersects(
|
||||
ST_GeomFromText('POLYGON ((%(minx)s %(miny)s,
|
||||
%(maxx)s %(miny)s,
|
||||
%(maxx)s %(maxy)s,
|
||||
%(minx)s %(maxy)s,
|
||||
%(minx)s %(miny)s))',%(db_srid)s),
|
||||
the_geom)"""
|
||||
conn = Session.connection()
|
||||
rows = conn.execute(statement,params)
|
||||
ids = [row['package_id'] for row in rows]
|
||||
|
||||
output = dict(count=len(ids),results=ids)
|
||||
|
||||
return self._finish_ok(output)
|
||||
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
from ckan.model import Session, repo
|
||||
from ckan.model import Package
|
||||
from ckan.lib.base import config
|
||||
|
||||
|
||||
log = __import__("logging").getLogger(__name__)
|
||||
|
||||
|
||||
def get_srid(crs):
|
||||
"""Returns the SRID for the provided CRS definition
|
||||
The CRS can be defined in the following formats
|
||||
- urn:ogc:def:crs:EPSG::4258
|
||||
- EPSG:4258
|
||||
- 4258
|
||||
"""
|
||||
|
||||
if ':' in crs:
|
||||
crs = crs.split(':')
|
||||
srid = crs[len(crs)-1]
|
||||
else:
|
||||
srid = crs
|
||||
|
||||
return int(srid)
|
||||
|
||||
def save_extent(package,extent=False):
|
||||
'''Updates the package extent in the package_extent geometry column
|
||||
If no extent provided (as a dict with minx,miny,maxx,maxy and srid keys),
|
||||
the values stored in the package extras are used'''
|
||||
|
||||
db_srid = int(config.get('ckan.spatial.srid', '4258'))
|
||||
conn = Session.connection()
|
||||
|
||||
srid = None
|
||||
if extent:
|
||||
minx = extent['minx']
|
||||
miny = extent['miny']
|
||||
maxx = extent['maxx']
|
||||
maxy = extent['maxy']
|
||||
if 'srid' in extent:
|
||||
srid = extent['srid']
|
||||
else:
|
||||
minx = float(package.extras.get('bbox-east-long'))
|
||||
miny = float(package.extras.get('bbox-south-lat'))
|
||||
maxx = float(package.extras.get('bbox-west-long'))
|
||||
maxy = float(package.extras.get('bbox-north-lat'))
|
||||
crs = package.extras.get('spatial-reference-system')
|
||||
if crs:
|
||||
srid = get_srid(crs)
|
||||
try:
|
||||
|
||||
# Check if extent already exists
|
||||
rows = conn.execute('SELECT package_id FROM package_extent WHERE package_id = %s',package.id).fetchall()
|
||||
update =(len(rows) > 0)
|
||||
|
||||
params = {'id':package.id, 'minx':minx,'miny':miny,'maxx':maxx,'maxy':maxy, 'db_srid': db_srid}
|
||||
|
||||
if update:
|
||||
# Update
|
||||
if srid and srid != db_srid:
|
||||
# We need to reproject the input geometry
|
||||
statement = """UPDATE package_extent SET
|
||||
the_geom = ST_Transform(
|
||||
ST_GeomFromText('POLYGON ((%(minx)s %(miny)s,
|
||||
%(maxx)s %(miny)s,
|
||||
%(maxx)s %(maxy)s,
|
||||
%(minx)s %(maxy)s,
|
||||
%(minx)s %(miny)s))',%(srid)s),
|
||||
%(db_srid)s)
|
||||
WHERE package_id = %(id)s
|
||||
"""
|
||||
params.update({'srid': srid})
|
||||
else:
|
||||
statement = """UPDATE package_extent SET
|
||||
the_geom = ST_GeomFromText('POLYGON ((%(minx)s %(miny)s,
|
||||
%(maxx)s %(miny)s,
|
||||
%(maxx)s %(maxy)s,
|
||||
%(minx)s %(maxy)s,
|
||||
%(minx)s %(miny)s))',%(db_srid)s)
|
||||
WHERE package_id = %(id)s
|
||||
"""
|
||||
msg = 'Updated extent for package %s'
|
||||
else:
|
||||
# Insert
|
||||
if srid and srid != db_srid:
|
||||
# We need to reproject the input geometry
|
||||
statement = """INSERT INTO package_extent (package_id,the_geom) VALUES (
|
||||
%(id)s,
|
||||
ST_Transform(
|
||||
ST_GeomFromText('POLYGON ((%(minx)s %(miny)s,
|
||||
%(maxx)s %(miny)s,
|
||||
%(maxx)s %(maxy)s,
|
||||
%(minx)s %(maxy)s,
|
||||
%(minx)s %(miny)s))',%(srid)s),
|
||||
%(db_srid))
|
||||
)"""
|
||||
params.update({'srid': srid})
|
||||
else:
|
||||
statement = """INSERT INTO package_extent (package_id,the_geom) VALUES (
|
||||
%(id)s,
|
||||
ST_GeomFromText('POLYGON ((%(minx)s %(miny)s,
|
||||
%(maxx)s %(miny)s,
|
||||
%(maxx)s %(maxy)s,
|
||||
%(minx)s %(maxy)s,
|
||||
%(minx)s %(miny)s))',%(db_srid)s))"""
|
||||
msg = 'Created new extent for package %s'
|
||||
|
||||
conn.execute(statement,params)
|
||||
|
||||
Session.commit()
|
||||
log.info(msg, package.id)
|
||||
return package
|
||||
except:
|
||||
log.error('An error occurred when saving the extent for package %s',package.id)
|
||||
raise Exception
|
|
@ -14,6 +14,20 @@ import html
|
|||
|
||||
log = getLogger(__name__)
|
||||
|
||||
class SpatialQuery(SingletonPlugin):
|
||||
|
||||
implements(IRoutes, inherit=True)
|
||||
|
||||
def before_map(self, map):
|
||||
|
||||
map.connect('api_spatial_query', '/api/2/search/package/geo',
|
||||
controller='ckanext.spatial.controllers.api:ApiController',
|
||||
action='spatial_query')
|
||||
|
||||
return map
|
||||
|
||||
|
||||
|
||||
class WMSPreview(SingletonPlugin):
|
||||
|
||||
implements(IGenshiStreamFilter)
|
||||
|
|
Loading…
Reference in New Issue