Refs #27736 -- Used decorators for GIS lookup registration.
This commit is contained in:
parent
7fffe3acc2
commit
378cf689d8
|
@ -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.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
|
||||||
from django.contrib.gis.db.models.fields import (
|
from django.contrib.gis.db.models.fields import (
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from django.contrib.gis import forms, gdal
|
from django.contrib.gis import forms, gdal
|
||||||
from django.contrib.gis.db.models.lookups import (
|
|
||||||
RasterBandTransform, gis_lookups,
|
|
||||||
)
|
|
||||||
from django.contrib.gis.db.models.proxy import SpatialProxy
|
from django.contrib.gis.db.models.proxy import SpatialProxy
|
||||||
from django.contrib.gis.gdal.error import GDALException
|
from django.contrib.gis.gdal.error import GDALException
|
||||||
from django.contrib.gis.geometry.backend import Geometry, GeometryException
|
from django.contrib.gis.geometry.backend import Geometry, GeometryException
|
||||||
|
@ -243,10 +240,6 @@ class BaseSpatialField(Field):
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
for klass in gis_lookups.values():
|
|
||||||
BaseSpatialField.register_lookup(klass)
|
|
||||||
|
|
||||||
|
|
||||||
class GeometryField(GeoSelectFormatMixin, BaseSpatialField):
|
class GeometryField(GeoSelectFormatMixin, BaseSpatialField):
|
||||||
"""
|
"""
|
||||||
The base Geometry field -- maps to the OpenGIS Specification Geometry type.
|
The base Geometry field -- maps to the OpenGIS Specification Geometry type.
|
||||||
|
@ -429,6 +422,7 @@ class RasterField(BaseSpatialField):
|
||||||
setattr(cls, self.attname, SpatialProxy(gdal.GDALRaster, self))
|
setattr(cls, self.attname, SpatialProxy(gdal.GDALRaster, self))
|
||||||
|
|
||||||
def get_transform(self, name):
|
def get_transform(self, name):
|
||||||
|
from django.contrib.gis.db.models.lookups import RasterBandTransform
|
||||||
try:
|
try:
|
||||||
band_index = int(name)
|
band_index = int(name)
|
||||||
return type(
|
return type(
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from django.contrib.gis.db.models.fields import BaseSpatialField
|
||||||
from django.db.models.expressions import Col, Expression
|
from django.db.models.expressions import Col, Expression
|
||||||
from django.db.models.lookups import Lookup, Transform
|
from django.db.models.lookups import Lookup, Transform
|
||||||
from django.db.models.sql.query import Query
|
from django.db.models.sql.query import Query
|
||||||
|
|
||||||
gis_lookups = {}
|
|
||||||
|
|
||||||
|
|
||||||
class RasterBandTransform(Transform):
|
class RasterBandTransform(Transform):
|
||||||
def as_sql(self, compiler, connection):
|
def as_sql(self, compiler, connection):
|
||||||
|
@ -107,6 +106,7 @@ class GISLookup(Lookup):
|
||||||
# Geometry operators
|
# Geometry operators
|
||||||
# ------------------
|
# ------------------
|
||||||
|
|
||||||
|
@BaseSpatialField.register_lookup
|
||||||
class OverlapsLeftLookup(GISLookup):
|
class OverlapsLeftLookup(GISLookup):
|
||||||
"""
|
"""
|
||||||
The overlaps_left operator returns true if A's bounding box overlaps or is to the
|
The overlaps_left operator returns true if A's bounding box overlaps or is to the
|
||||||
|
@ -115,9 +115,7 @@ class OverlapsLeftLookup(GISLookup):
|
||||||
lookup_name = 'overlaps_left'
|
lookup_name = 'overlaps_left'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['overlaps_left'] = OverlapsLeftLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class OverlapsRightLookup(GISLookup):
|
class OverlapsRightLookup(GISLookup):
|
||||||
"""
|
"""
|
||||||
The 'overlaps_right' operator returns true if A's bounding box overlaps or is to the
|
The 'overlaps_right' operator returns true if A's bounding box overlaps or is to the
|
||||||
|
@ -126,9 +124,7 @@ class OverlapsRightLookup(GISLookup):
|
||||||
lookup_name = 'overlaps_right'
|
lookup_name = 'overlaps_right'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['overlaps_right'] = OverlapsRightLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class OverlapsBelowLookup(GISLookup):
|
class OverlapsBelowLookup(GISLookup):
|
||||||
"""
|
"""
|
||||||
The 'overlaps_below' operator returns true if A's bounding box overlaps or is below
|
The 'overlaps_below' operator returns true if A's bounding box overlaps or is below
|
||||||
|
@ -137,9 +133,7 @@ class OverlapsBelowLookup(GISLookup):
|
||||||
lookup_name = 'overlaps_below'
|
lookup_name = 'overlaps_below'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['overlaps_below'] = OverlapsBelowLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class OverlapsAboveLookup(GISLookup):
|
class OverlapsAboveLookup(GISLookup):
|
||||||
"""
|
"""
|
||||||
The 'overlaps_above' operator returns true if A's bounding box overlaps or is above
|
The 'overlaps_above' operator returns true if A's bounding box overlaps or is above
|
||||||
|
@ -148,9 +142,7 @@ class OverlapsAboveLookup(GISLookup):
|
||||||
lookup_name = 'overlaps_above'
|
lookup_name = 'overlaps_above'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['overlaps_above'] = OverlapsAboveLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class LeftLookup(GISLookup):
|
class LeftLookup(GISLookup):
|
||||||
"""
|
"""
|
||||||
The 'left' operator returns true if A's bounding box is strictly to the left
|
The 'left' operator returns true if A's bounding box is strictly to the left
|
||||||
|
@ -159,9 +151,7 @@ class LeftLookup(GISLookup):
|
||||||
lookup_name = 'left'
|
lookup_name = 'left'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['left'] = LeftLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class RightLookup(GISLookup):
|
class RightLookup(GISLookup):
|
||||||
"""
|
"""
|
||||||
The 'right' operator returns true if A's bounding box is strictly to the right
|
The 'right' operator returns true if A's bounding box is strictly to the right
|
||||||
|
@ -170,9 +160,7 @@ class RightLookup(GISLookup):
|
||||||
lookup_name = 'right'
|
lookup_name = 'right'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['right'] = RightLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class StrictlyBelowLookup(GISLookup):
|
class StrictlyBelowLookup(GISLookup):
|
||||||
"""
|
"""
|
||||||
The 'strictly_below' operator returns true if A's bounding box is strictly below B's
|
The 'strictly_below' operator returns true if A's bounding box is strictly below B's
|
||||||
|
@ -181,9 +169,7 @@ class StrictlyBelowLookup(GISLookup):
|
||||||
lookup_name = 'strictly_below'
|
lookup_name = 'strictly_below'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['strictly_below'] = StrictlyBelowLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class StrictlyAboveLookup(GISLookup):
|
class StrictlyAboveLookup(GISLookup):
|
||||||
"""
|
"""
|
||||||
The 'strictly_above' operator returns true if A's bounding box is strictly above B's
|
The 'strictly_above' operator returns true if A's bounding box is strictly above B's
|
||||||
|
@ -192,9 +178,7 @@ class StrictlyAboveLookup(GISLookup):
|
||||||
lookup_name = 'strictly_above'
|
lookup_name = 'strictly_above'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['strictly_above'] = StrictlyAboveLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class SameAsLookup(GISLookup):
|
class SameAsLookup(GISLookup):
|
||||||
"""
|
"""
|
||||||
The "~=" operator is the "same as" operator. It tests actual geometric
|
The "~=" operator is the "same as" operator. It tests actual geometric
|
||||||
|
@ -204,17 +188,10 @@ class SameAsLookup(GISLookup):
|
||||||
lookup_name = 'same_as'
|
lookup_name = 'same_as'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['same_as'] = SameAsLookup
|
BaseSpatialField.register_lookup(SameAsLookup, 'exact')
|
||||||
|
|
||||||
|
|
||||||
class ExactLookup(SameAsLookup):
|
|
||||||
# Alias of same_as
|
|
||||||
lookup_name = 'exact'
|
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['exact'] = ExactLookup
|
|
||||||
|
|
||||||
|
|
||||||
|
@BaseSpatialField.register_lookup
|
||||||
class BBContainsLookup(GISLookup):
|
class BBContainsLookup(GISLookup):
|
||||||
"""
|
"""
|
||||||
The 'bbcontains' operator returns true if A's bounding box completely contains
|
The 'bbcontains' operator returns true if A's bounding box completely contains
|
||||||
|
@ -223,9 +200,7 @@ class BBContainsLookup(GISLookup):
|
||||||
lookup_name = 'bbcontains'
|
lookup_name = 'bbcontains'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['bbcontains'] = BBContainsLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class BBOverlapsLookup(GISLookup):
|
class BBOverlapsLookup(GISLookup):
|
||||||
"""
|
"""
|
||||||
The 'bboverlaps' operator returns true if A's bounding box overlaps B's bounding box.
|
The 'bboverlaps' operator returns true if A's bounding box overlaps B's bounding box.
|
||||||
|
@ -233,9 +208,7 @@ class BBOverlapsLookup(GISLookup):
|
||||||
lookup_name = 'bboverlaps'
|
lookup_name = 'bboverlaps'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['bboverlaps'] = BBOverlapsLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class ContainedLookup(GISLookup):
|
class ContainedLookup(GISLookup):
|
||||||
"""
|
"""
|
||||||
The 'contained' operator returns true if A's bounding box is completely contained
|
The 'contained' operator returns true if A's bounding box is completely contained
|
||||||
|
@ -244,69 +217,51 @@ class ContainedLookup(GISLookup):
|
||||||
lookup_name = 'contained'
|
lookup_name = 'contained'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['contained'] = ContainedLookup
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------
|
# ------------------
|
||||||
# Geometry functions
|
# Geometry functions
|
||||||
# ------------------
|
# ------------------
|
||||||
|
|
||||||
|
@BaseSpatialField.register_lookup
|
||||||
class ContainsLookup(GISLookup):
|
class ContainsLookup(GISLookup):
|
||||||
lookup_name = 'contains'
|
lookup_name = 'contains'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['contains'] = ContainsLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class ContainsProperlyLookup(GISLookup):
|
class ContainsProperlyLookup(GISLookup):
|
||||||
lookup_name = 'contains_properly'
|
lookup_name = 'contains_properly'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['contains_properly'] = ContainsProperlyLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class CoveredByLookup(GISLookup):
|
class CoveredByLookup(GISLookup):
|
||||||
lookup_name = 'coveredby'
|
lookup_name = 'coveredby'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['coveredby'] = CoveredByLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class CoversLookup(GISLookup):
|
class CoversLookup(GISLookup):
|
||||||
lookup_name = 'covers'
|
lookup_name = 'covers'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['covers'] = CoversLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class CrossesLookup(GISLookup):
|
class CrossesLookup(GISLookup):
|
||||||
lookup_name = 'crosses'
|
lookup_name = 'crosses'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['crosses'] = CrossesLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class DisjointLookup(GISLookup):
|
class DisjointLookup(GISLookup):
|
||||||
lookup_name = 'disjoint'
|
lookup_name = 'disjoint'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['disjoint'] = DisjointLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class EqualsLookup(GISLookup):
|
class EqualsLookup(GISLookup):
|
||||||
lookup_name = 'equals'
|
lookup_name = 'equals'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['equals'] = EqualsLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class IntersectsLookup(GISLookup):
|
class IntersectsLookup(GISLookup):
|
||||||
lookup_name = 'intersects'
|
lookup_name = 'intersects'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['intersects'] = IntersectsLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class IsValidLookup(GISLookup):
|
class IsValidLookup(GISLookup):
|
||||||
lookup_name = 'isvalid'
|
lookup_name = 'isvalid'
|
||||||
sql_template = '%(func)s(%(lhs)s)'
|
sql_template = '%(func)s(%(lhs)s)'
|
||||||
|
@ -322,16 +277,12 @@ class IsValidLookup(GISLookup):
|
||||||
return sql, params
|
return sql, params
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['isvalid'] = IsValidLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class OverlapsLookup(GISLookup):
|
class OverlapsLookup(GISLookup):
|
||||||
lookup_name = 'overlaps'
|
lookup_name = 'overlaps'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['overlaps'] = OverlapsLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class RelateLookup(GISLookup):
|
class RelateLookup(GISLookup):
|
||||||
lookup_name = 'relate'
|
lookup_name = 'relate'
|
||||||
sql_template = '%(func)s(%(lhs)s, %(rhs)s, %%s)'
|
sql_template = '%(func)s(%(lhs)s, %(rhs)s, %%s)'
|
||||||
|
@ -351,23 +302,16 @@ class RelateLookup(GISLookup):
|
||||||
return super().get_db_prep_lookup(value, connection)
|
return super().get_db_prep_lookup(value, connection)
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['relate'] = RelateLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class TouchesLookup(GISLookup):
|
class TouchesLookup(GISLookup):
|
||||||
lookup_name = 'touches'
|
lookup_name = 'touches'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['touches'] = TouchesLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class WithinLookup(GISLookup):
|
class WithinLookup(GISLookup):
|
||||||
lookup_name = 'within'
|
lookup_name = 'within'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['within'] = WithinLookup
|
|
||||||
|
|
||||||
|
|
||||||
class DistanceLookupBase(GISLookup):
|
class DistanceLookupBase(GISLookup):
|
||||||
distance = True
|
distance = True
|
||||||
sql_template = '%(func)s(%(lhs)s, %(rhs)s) %(op)s %(value)s'
|
sql_template = '%(func)s(%(lhs)s, %(rhs)s) %(op)s %(value)s'
|
||||||
|
@ -400,37 +344,27 @@ class DistanceLookupBase(GISLookup):
|
||||||
return (rhs, params)
|
return (rhs, params)
|
||||||
|
|
||||||
|
|
||||||
|
@BaseSpatialField.register_lookup
|
||||||
class DWithinLookup(DistanceLookupBase):
|
class DWithinLookup(DistanceLookupBase):
|
||||||
lookup_name = 'dwithin'
|
lookup_name = 'dwithin'
|
||||||
sql_template = '%(func)s(%(lhs)s, %(rhs)s, %%s)'
|
sql_template = '%(func)s(%(lhs)s, %(rhs)s, %%s)'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['dwithin'] = DWithinLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class DistanceGTLookup(DistanceLookupBase):
|
class DistanceGTLookup(DistanceLookupBase):
|
||||||
lookup_name = 'distance_gt'
|
lookup_name = 'distance_gt'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['distance_gt'] = DistanceGTLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class DistanceGTELookup(DistanceLookupBase):
|
class DistanceGTELookup(DistanceLookupBase):
|
||||||
lookup_name = 'distance_gte'
|
lookup_name = 'distance_gte'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['distance_gte'] = DistanceGTELookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class DistanceLTLookup(DistanceLookupBase):
|
class DistanceLTLookup(DistanceLookupBase):
|
||||||
lookup_name = 'distance_lt'
|
lookup_name = 'distance_lt'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['distance_lt'] = DistanceLTLookup
|
@BaseSpatialField.register_lookup
|
||||||
|
|
||||||
|
|
||||||
class DistanceLTELookup(DistanceLookupBase):
|
class DistanceLTELookup(DistanceLookupBase):
|
||||||
lookup_name = 'distance_lte'
|
lookup_name = 'distance_lte'
|
||||||
|
|
||||||
|
|
||||||
gis_lookups['distance_lte'] = DistanceLTELookup
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
from django.contrib.gis.db.models.fields import BaseSpatialField
|
||||||
from django.contrib.gis.db.models.functions import Distance
|
from django.contrib.gis.db.models.functions import Distance
|
||||||
from django.contrib.gis.db.models.lookups import (
|
from django.contrib.gis.db.models.lookups import DistanceLookupBase, GISLookup
|
||||||
DistanceLookupBase, gis_lookups,
|
|
||||||
)
|
|
||||||
from django.contrib.gis.gdal import HAS_GDAL
|
from django.contrib.gis.gdal import HAS_GDAL
|
||||||
from django.contrib.gis.geos import GEOSGeometry
|
from django.contrib.gis.geos import GEOSGeometry
|
||||||
from django.contrib.gis.measure import D
|
from django.contrib.gis.measure import D
|
||||||
|
@ -130,7 +129,9 @@ class RasterFieldTest(TransactionTestCase):
|
||||||
stx_pnt.transform(3086)
|
stx_pnt.transform(3086)
|
||||||
|
|
||||||
# Loop through all the GIS lookups.
|
# Loop through all the GIS lookups.
|
||||||
for name, lookup in gis_lookups.items():
|
for name, lookup in BaseSpatialField.get_lookups().items():
|
||||||
|
if not isinstance(lookup, GISLookup):
|
||||||
|
continue
|
||||||
# Construct lookup filter strings.
|
# Construct lookup filter strings.
|
||||||
combo_keys = [
|
combo_keys = [
|
||||||
field + name for field in [
|
field + name for field in [
|
||||||
|
|
Loading…
Reference in New Issue