Made isvalid lookup use IsValid function to decrease code redundancy.
This commit is contained in:
parent
1d070d027c
commit
9cd6ba991f
|
@ -68,7 +68,7 @@ class BaseSpatialFeatures:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supports_isvalid_lookup(self):
|
def supports_isvalid_lookup(self):
|
||||||
return 'isvalid' in self.connection.ops.gis_operators
|
return self.has_IsValid_function
|
||||||
|
|
||||||
# Is the aggregate supported by the database?
|
# Is the aggregate supported by the database?
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -51,10 +51,6 @@ class SDORelate(SpatialOperator):
|
||||||
return super().as_sql(connection, lookup, template_params, sql_params)
|
return super().as_sql(connection, lookup, template_params, sql_params)
|
||||||
|
|
||||||
|
|
||||||
class SDOIsValid(SpatialOperator):
|
|
||||||
sql_template = "%%(func)s(%%(lhs)s, %s) = 'TRUE'" % DEFAULT_TOLERANCE
|
|
||||||
|
|
||||||
|
|
||||||
class OracleOperations(BaseSpatialOperations, DatabaseOperations):
|
class OracleOperations(BaseSpatialOperations, DatabaseOperations):
|
||||||
|
|
||||||
name = 'oracle'
|
name = 'oracle'
|
||||||
|
@ -100,7 +96,6 @@ class OracleOperations(BaseSpatialOperations, DatabaseOperations):
|
||||||
'covers': SDOOperator(func='SDO_COVERS'),
|
'covers': SDOOperator(func='SDO_COVERS'),
|
||||||
'disjoint': SDODisjoint(),
|
'disjoint': SDODisjoint(),
|
||||||
'intersects': SDOOperator(func='SDO_OVERLAPBDYINTERSECT'), # TODO: Is this really the same as ST_Intersects()?
|
'intersects': SDOOperator(func='SDO_OVERLAPBDYINTERSECT'), # TODO: Is this really the same as ST_Intersects()?
|
||||||
'isvalid': SDOIsValid(func='SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT'),
|
|
||||||
'equals': SDOOperator(func='SDO_EQUAL'),
|
'equals': SDOOperator(func='SDO_EQUAL'),
|
||||||
'exact': SDOOperator(func='SDO_EQUAL'),
|
'exact': SDOOperator(func='SDO_EQUAL'),
|
||||||
'overlaps': SDOOperator(func='SDO_OVERLAPS'),
|
'overlaps': SDOOperator(func='SDO_OVERLAPS'),
|
||||||
|
|
|
@ -134,7 +134,6 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations):
|
||||||
'disjoint': PostGISOperator(func='ST_Disjoint', raster=BILATERAL),
|
'disjoint': PostGISOperator(func='ST_Disjoint', raster=BILATERAL),
|
||||||
'equals': PostGISOperator(func='ST_Equals'),
|
'equals': PostGISOperator(func='ST_Equals'),
|
||||||
'intersects': PostGISOperator(func='ST_Intersects', geography=True, raster=BILATERAL),
|
'intersects': PostGISOperator(func='ST_Intersects', geography=True, raster=BILATERAL),
|
||||||
'isvalid': PostGISOperator(func='ST_IsValid'),
|
|
||||||
'overlaps': PostGISOperator(func='ST_Overlaps', raster=BILATERAL),
|
'overlaps': PostGISOperator(func='ST_Overlaps', raster=BILATERAL),
|
||||||
'relate': PostGISOperator(func='ST_Relate'),
|
'relate': PostGISOperator(func='ST_Relate'),
|
||||||
'touches': PostGISOperator(func='ST_Touches', raster=BILATERAL),
|
'touches': PostGISOperator(func='ST_Touches', raster=BILATERAL),
|
||||||
|
|
|
@ -48,8 +48,6 @@ class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations):
|
||||||
select = 'AsText(%s)'
|
select = 'AsText(%s)'
|
||||||
|
|
||||||
gis_operators = {
|
gis_operators = {
|
||||||
# Unary predicates
|
|
||||||
'isvalid': SpatialOperator(func='IsValid'),
|
|
||||||
# Binary predicates
|
# Binary predicates
|
||||||
'equals': SpatialOperator(func='Equals'),
|
'equals': SpatialOperator(func='Equals'),
|
||||||
'disjoint': SpatialOperator(func='Disjoint'),
|
'disjoint': SpatialOperator(func='Disjoint'),
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from django.db.models import * # NOQA isort:skip
|
from django.db.models import * # NOQA isort:skip
|
||||||
from django.db.models import __all__ as models_all # isort:skip
|
from django.db.models import __all__ as models_all # isort:skip
|
||||||
|
import django.contrib.gis.db.models.functions # NOQA
|
||||||
import django.contrib.gis.db.models.lookups # NOQA
|
import django.contrib.gis.db.models.lookups # NOQA
|
||||||
from django.contrib.gis.db.models.aggregates import * # NOQA
|
from django.contrib.gis.db.models.aggregates import * # NOQA
|
||||||
from django.contrib.gis.db.models.aggregates import __all__ as aggregates_all
|
from django.contrib.gis.db.models.aggregates import __all__ as aggregates_all
|
||||||
|
|
|
@ -1,19 +1,23 @@
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
from django.contrib.gis.db.models.fields import GeometryField, RasterField
|
from django.contrib.gis.db.models.fields import (
|
||||||
|
BaseSpatialField, GeometryField, RasterField,
|
||||||
|
)
|
||||||
from django.contrib.gis.db.models.sql import AreaField
|
from django.contrib.gis.db.models.sql import AreaField
|
||||||
from django.contrib.gis.geometry.backend import Geometry
|
from django.contrib.gis.geometry.backend import Geometry
|
||||||
from django.contrib.gis.measure import (
|
from django.contrib.gis.measure import (
|
||||||
Area as AreaMeasure, Distance as DistanceMeasure,
|
Area as AreaMeasure, Distance as DistanceMeasure,
|
||||||
)
|
)
|
||||||
from django.core.exceptions import FieldError
|
from django.core.exceptions import FieldError
|
||||||
from django.db.models import BooleanField, FloatField, IntegerField, TextField
|
from django.db.models import (
|
||||||
|
BooleanField, FloatField, IntegerField, TextField, Transform,
|
||||||
|
)
|
||||||
from django.db.models.expressions import Func, Value
|
from django.db.models.expressions import Func, Value
|
||||||
|
|
||||||
NUMERIC_TYPES = (int, float, Decimal)
|
NUMERIC_TYPES = (int, float, Decimal)
|
||||||
|
|
||||||
|
|
||||||
class GeoFunc(Func):
|
class GeoFuncMixin:
|
||||||
function = None
|
function = None
|
||||||
output_field_class = None
|
output_field_class = None
|
||||||
geom_param_pos = 0
|
geom_param_pos = 0
|
||||||
|
@ -70,6 +74,10 @@ class GeoFunc(Func):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class GeoFunc(GeoFuncMixin, Func):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class GeomValue(Value):
|
class GeomValue(Value):
|
||||||
geography = False
|
geography = False
|
||||||
|
|
||||||
|
@ -319,8 +327,10 @@ class Intersection(OracleToleranceMixin, GeoFuncWithGeoParam):
|
||||||
arity = 2
|
arity = 2
|
||||||
|
|
||||||
|
|
||||||
class IsValid(OracleToleranceMixin, GeoFunc):
|
@BaseSpatialField.register_lookup
|
||||||
output_field_class = BooleanField
|
class IsValid(OracleToleranceMixin, GeoFuncMixin, Transform):
|
||||||
|
lookup_name = 'isvalid'
|
||||||
|
output_field = BooleanField()
|
||||||
|
|
||||||
def as_oracle(self, compiler, connection, **extra_context):
|
def as_oracle(self, compiler, connection, **extra_context):
|
||||||
sql, params = super().as_oracle(compiler, connection, **extra_context)
|
sql, params = super().as_oracle(compiler, connection, **extra_context)
|
||||||
|
|
|
@ -261,22 +261,6 @@ class IntersectsLookup(GISLookup):
|
||||||
lookup_name = 'intersects'
|
lookup_name = 'intersects'
|
||||||
|
|
||||||
|
|
||||||
@BaseSpatialField.register_lookup
|
|
||||||
class IsValidLookup(GISLookup):
|
|
||||||
lookup_name = 'isvalid'
|
|
||||||
sql_template = '%(func)s(%(lhs)s)'
|
|
||||||
|
|
||||||
def as_sql(self, compiler, connection):
|
|
||||||
if self.lhs.field.geom_type == 'RASTER':
|
|
||||||
raise ValueError('The isvalid lookup is only available on geometry fields.')
|
|
||||||
gis_op = connection.ops.gis_operators[self.lookup_name]
|
|
||||||
sql, params = self.process_lhs(compiler, connection)
|
|
||||||
sql, params = gis_op.as_sql(connection, self, {'func': gis_op.func, 'lhs': sql}, params)
|
|
||||||
if not self.rhs:
|
|
||||||
sql = 'NOT ' + sql
|
|
||||||
return sql, params
|
|
||||||
|
|
||||||
|
|
||||||
@BaseSpatialField.register_lookup
|
@BaseSpatialField.register_lookup
|
||||||
class OverlapsLookup(GISLookup):
|
class OverlapsLookup(GISLookup):
|
||||||
lookup_name = 'overlaps'
|
lookup_name = 'overlaps'
|
||||||
|
|
|
@ -271,8 +271,8 @@ class RasterFieldTest(TransactionTestCase):
|
||||||
|
|
||||||
def test_isvalid_lookup_with_raster_error(self):
|
def test_isvalid_lookup_with_raster_error(self):
|
||||||
qs = RasterModel.objects.filter(rast__isvalid=True)
|
qs = RasterModel.objects.filter(rast__isvalid=True)
|
||||||
msg = 'The isvalid lookup is only available on geometry fields.'
|
msg = 'Geometry functions not supported for raster fields.'
|
||||||
with self.assertRaisesMessage(ValueError, msg):
|
with self.assertRaisesMessage(TypeError, msg):
|
||||||
qs.count()
|
qs.count()
|
||||||
|
|
||||||
def test_result_of_gis_lookup_with_rasters(self):
|
def test_result_of_gis_lookup_with_rasters(self):
|
||||||
|
|
Loading…
Reference in New Issue