Refs #25588 -- Fixed GDAL dependency in spatial lookups.
This commit is contained in:
parent
0e7e47b5d7
commit
9bb1b4b7f6
|
@ -182,6 +182,25 @@ class BaseSpatialField(Field):
|
||||||
else:
|
else:
|
||||||
return connection.ops.Adapter(self.get_prep_value(value))
|
return connection.ops.Adapter(self.get_prep_value(value))
|
||||||
|
|
||||||
|
def get_raster_prep_value(self, value, is_candidate):
|
||||||
|
"""
|
||||||
|
Return a GDALRaster if conversion is successful, otherwise return None.
|
||||||
|
"""
|
||||||
|
from django.contrib.gis.gdal import GDALRaster
|
||||||
|
|
||||||
|
if isinstance(value, GDALRaster):
|
||||||
|
return value
|
||||||
|
elif is_candidate:
|
||||||
|
try:
|
||||||
|
return GDALRaster(value)
|
||||||
|
except GDALException:
|
||||||
|
pass
|
||||||
|
elif isinstance(value, dict):
|
||||||
|
try:
|
||||||
|
return GDALRaster(value)
|
||||||
|
except GDALException:
|
||||||
|
raise ValueError("Couldn't create spatial object from lookup value '%s'." % value)
|
||||||
|
|
||||||
def get_prep_value(self, value):
|
def get_prep_value(self, value):
|
||||||
"""
|
"""
|
||||||
Spatial lookup values are either a parameter that is (or may be
|
Spatial lookup values are either a parameter that is (or may be
|
||||||
|
@ -190,9 +209,8 @@ class BaseSpatialField(Field):
|
||||||
geometry or raster value properly and preserves any other lookup
|
geometry or raster value properly and preserves any other lookup
|
||||||
parameters.
|
parameters.
|
||||||
"""
|
"""
|
||||||
from django.contrib.gis.gdal import GDALRaster
|
|
||||||
|
|
||||||
value = super(BaseSpatialField, self).get_prep_value(value)
|
value = super(BaseSpatialField, self).get_prep_value(value)
|
||||||
|
|
||||||
# For IsValid lookups, boolean values are allowed.
|
# For IsValid lookups, boolean values are allowed.
|
||||||
if isinstance(value, (Expression, bool)):
|
if isinstance(value, (Expression, bool)):
|
||||||
return value
|
return value
|
||||||
|
@ -205,20 +223,22 @@ class BaseSpatialField(Field):
|
||||||
|
|
||||||
# When the input is not a geometry or raster, attempt to construct one
|
# When the input is not a geometry or raster, attempt to construct one
|
||||||
# from the given string input.
|
# from the given string input.
|
||||||
if isinstance(obj, (Geometry, GDALRaster)):
|
if isinstance(obj, Geometry):
|
||||||
pass
|
pass
|
||||||
elif isinstance(obj, (bytes, six.string_types)) or hasattr(obj, '__geo_interface__'):
|
else:
|
||||||
|
# Check if input is a candidate for conversion to raster or geometry.
|
||||||
|
is_candidate = isinstance(obj, (bytes, six.string_types)) or hasattr(obj, '__geo_interface__')
|
||||||
|
# With GDAL installed, try to convert the input to raster.
|
||||||
|
raster = False
|
||||||
|
if HAS_GDAL:
|
||||||
|
raster = self.get_raster_prep_value(obj, is_candidate)
|
||||||
|
|
||||||
|
if raster:
|
||||||
|
obj = raster
|
||||||
|
elif is_candidate:
|
||||||
try:
|
try:
|
||||||
obj = Geometry(obj)
|
obj = Geometry(obj)
|
||||||
except (GeometryException, GDALException):
|
except (GeometryException, GDALException):
|
||||||
try:
|
|
||||||
obj = GDALRaster(obj)
|
|
||||||
except GDALException:
|
|
||||||
raise ValueError("Couldn't create spatial object from lookup value '%s'." % obj)
|
|
||||||
elif isinstance(obj, dict):
|
|
||||||
try:
|
|
||||||
obj = GDALRaster(obj)
|
|
||||||
except GDALException:
|
|
||||||
raise ValueError("Couldn't create spatial object from lookup value '%s'." % obj)
|
raise ValueError("Couldn't create spatial object from lookup value '%s'." % obj)
|
||||||
else:
|
else:
|
||||||
raise ValueError('Cannot use object with type %s for a spatial lookup parameter.' % type(obj).__name__)
|
raise ValueError('Cannot use object with type %s for a spatial lookup parameter.' % type(obj).__name__)
|
||||||
|
@ -295,48 +315,6 @@ class GeometryField(GeoSelectFormatMixin, BaseSpatialField):
|
||||||
"""
|
"""
|
||||||
return connection.ops.get_distance(self, value, lookup_type)
|
return connection.ops.get_distance(self, value, lookup_type)
|
||||||
|
|
||||||
def get_prep_value(self, value):
|
|
||||||
"""
|
|
||||||
Spatial lookup values are either a parameter that is (or may be
|
|
||||||
converted to) a geometry, or a sequence of lookup values that
|
|
||||||
begins with a geometry. This routine will setup the geometry
|
|
||||||
value properly, and preserve any other lookup parameters before
|
|
||||||
returning to the caller.
|
|
||||||
"""
|
|
||||||
from django.contrib.gis.gdal import GDALRaster
|
|
||||||
|
|
||||||
value = super(GeometryField, self).get_prep_value(value)
|
|
||||||
if isinstance(value, (Expression, bool)):
|
|
||||||
return value
|
|
||||||
elif isinstance(value, (tuple, list)):
|
|
||||||
geom = value[0]
|
|
||||||
seq_value = True
|
|
||||||
else:
|
|
||||||
geom = value
|
|
||||||
seq_value = False
|
|
||||||
|
|
||||||
# When the input is not a GEOS geometry, attempt to construct one
|
|
||||||
# from the given string input.
|
|
||||||
if isinstance(geom, (Geometry, GDALRaster)):
|
|
||||||
pass
|
|
||||||
elif isinstance(geom, (bytes, six.string_types)) or hasattr(geom, '__geo_interface__'):
|
|
||||||
try:
|
|
||||||
geom = Geometry(geom)
|
|
||||||
except GeometryException:
|
|
||||||
raise ValueError('Could not create geometry from lookup value.')
|
|
||||||
else:
|
|
||||||
raise ValueError('Cannot use object with type %s for a geometry lookup parameter.' % type(geom).__name__)
|
|
||||||
|
|
||||||
# Assigning the SRID value.
|
|
||||||
geom.srid = self.get_srid(geom)
|
|
||||||
|
|
||||||
if seq_value:
|
|
||||||
lookup_val = [geom]
|
|
||||||
lookup_val.extend(value[1:])
|
|
||||||
return tuple(lookup_val)
|
|
||||||
else:
|
|
||||||
return geom
|
|
||||||
|
|
||||||
def from_db_value(self, value, expression, connection, context):
|
def from_db_value(self, value, expression, connection, context):
|
||||||
if value:
|
if value:
|
||||||
if not isinstance(value, Geometry):
|
if not isinstance(value, Geometry):
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from unittest import skipUnless
|
||||||
|
|
||||||
from django.contrib.gis.db.models import fields
|
from django.contrib.gis.db.models import fields
|
||||||
|
from django.contrib.gis.gdal import HAS_GDAL
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.db import connection, migrations, models
|
from django.db import connection, migrations, models
|
||||||
from django.db.migrations.migration import Migration
|
from django.db.migrations.migration import Migration
|
||||||
|
@ -114,6 +117,7 @@ class OperationTests(TransactionTestCase):
|
||||||
self.assertSpatialIndexExists('gis_neighborhood', 'heatmap')
|
self.assertSpatialIndexExists('gis_neighborhood', 'heatmap')
|
||||||
|
|
||||||
@skipIfDBFeature('supports_raster')
|
@skipIfDBFeature('supports_raster')
|
||||||
|
@skipUnless(HAS_GDAL, 'A different error is raised if GDAL is not installed.')
|
||||||
def test_create_raster_model_on_db_without_raster_support(self):
|
def test_create_raster_model_on_db_without_raster_support(self):
|
||||||
"""
|
"""
|
||||||
Test creating a model with a raster field on a db without raster support.
|
Test creating a model with a raster field on a db without raster support.
|
||||||
|
@ -123,6 +127,7 @@ class OperationTests(TransactionTestCase):
|
||||||
self.set_up_test_model(True)
|
self.set_up_test_model(True)
|
||||||
|
|
||||||
@skipIfDBFeature('supports_raster')
|
@skipIfDBFeature('supports_raster')
|
||||||
|
@skipUnless(HAS_GDAL, 'A different error is raised if GDAL is not installed.')
|
||||||
def test_add_raster_field_on_db_without_raster_support(self):
|
def test_add_raster_field_on_db_without_raster_support(self):
|
||||||
"""
|
"""
|
||||||
Test adding a raster field on a db without raster support.
|
Test adding a raster field on a db without raster support.
|
||||||
|
|
Loading…
Reference in New Issue