Commit 9bb1b4b7 authored by Daniel Wiesmann's avatar Daniel Wiesmann
Browse files

Refs #25588 -- Fixed GDAL dependency in spatial lookups.

parent 0e7e47b5
Loading
Loading
Loading
Loading
+36 −58
Original line number Diff line number Diff line
@@ -182,6 +182,25 @@ class BaseSpatialField(Field):
        else:
            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):
        """
        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
        parameters.
        """
        from django.contrib.gis.gdal import GDALRaster

        value = super(BaseSpatialField, self).get_prep_value(value)

        # For IsValid lookups, boolean values are allowed.
        if isinstance(value, (Expression, bool)):
            return value
@@ -205,20 +223,22 @@ class BaseSpatialField(Field):

        # When the input is not a geometry or raster, attempt to construct one
        # from the given string input.
        if isinstance(obj, (Geometry, GDALRaster)):
        if isinstance(obj, Geometry):
            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:
                    obj = Geometry(obj)
                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)
            else:
                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)

    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):
        if value:
            if not isinstance(value, Geometry):
+5 −0
Original line number Diff line number Diff line
from __future__ import unicode_literals

from unittest import skipUnless

from django.contrib.gis.db.models import fields
from django.contrib.gis.gdal import HAS_GDAL
from django.core.exceptions import ImproperlyConfigured
from django.db import connection, migrations, models
from django.db.migrations.migration import Migration
@@ -114,6 +117,7 @@ class OperationTests(TransactionTestCase):
            self.assertSpatialIndexExists('gis_neighborhood', 'heatmap')

    @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):
        """
        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)

    @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):
        """
        Test adding a raster field on a db without raster support.