summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Fedoseev <fedoseev.sergey@gmail.com>2017-03-28 07:20:18 +0500
committerTim Graham <timograham@gmail.com>2017-03-27 22:20:18 -0400
commitd47de2e09d12636e5d527136b97f084da990c04f (patch)
treecb759d8acb7c47de4852b1995507879db3dd5abd
parent24d53786d414586bb56243758cec41e802e8947d (diff)
Refs #27736 -- Used decorators for GIS lookup registration.
-rw-r--r--django/contrib/gis/db/models/__init__.py1
-rw-r--r--django/contrib/gis/db/models/fields.py8
-rw-r--r--django/contrib/gis/db/models/lookups.py130
-rw-r--r--tests/gis_tests/rasterapp/test_rasterfield.py9
4 files changed, 39 insertions, 109 deletions
diff --git a/django/contrib/gis/db/models/__init__.py b/django/contrib/gis/db/models/__init__.py
index 5f6c2374a7..31ca0001df 100644
--- a/django/contrib/gis/db/models/__init__.py
+++ b/django/contrib/gis/db/models/__init__.py
@@ -1,5 +1,6 @@
from django.db.models import * # NOQA 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 __all__ as aggregates_all
from django.contrib.gis.db.models.fields import (
diff --git a/django/contrib/gis/db/models/fields.py b/django/contrib/gis/db/models/fields.py
index 9ea62400c5..77b81cddd1 100644
--- a/django/contrib/gis/db/models/fields.py
+++ b/django/contrib/gis/db/models/fields.py
@@ -1,9 +1,6 @@
from collections import defaultdict
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.gdal.error import GDALException
from django.contrib.gis.geometry.backend import Geometry, GeometryException
@@ -243,10 +240,6 @@ class BaseSpatialField(Field):
return obj
-for klass in gis_lookups.values():
- BaseSpatialField.register_lookup(klass)
-
-
class GeometryField(GeoSelectFormatMixin, BaseSpatialField):
"""
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))
def get_transform(self, name):
+ from django.contrib.gis.db.models.lookups import RasterBandTransform
try:
band_index = int(name)
return type(
diff --git a/django/contrib/gis/db/models/lookups.py b/django/contrib/gis/db/models/lookups.py
index 489eef1728..c0d1934965 100644
--- a/django/contrib/gis/db/models/lookups.py
+++ b/django/contrib/gis/db/models/lookups.py
@@ -1,11 +1,10 @@
import re
+from django.contrib.gis.db.models.fields import BaseSpatialField
from django.db.models.expressions import Col, Expression
from django.db.models.lookups import Lookup, Transform
from django.db.models.sql.query import Query
-gis_lookups = {}
-
class RasterBandTransform(Transform):
def as_sql(self, compiler, connection):
@@ -107,6 +106,7 @@ class GISLookup(Lookup):
# Geometry operators
# ------------------
+@BaseSpatialField.register_lookup
class OverlapsLeftLookup(GISLookup):
"""
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'
-gis_lookups['overlaps_left'] = OverlapsLeftLookup
-
-
+@BaseSpatialField.register_lookup
class OverlapsRightLookup(GISLookup):
"""
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'
-gis_lookups['overlaps_right'] = OverlapsRightLookup
-
-
+@BaseSpatialField.register_lookup
class OverlapsBelowLookup(GISLookup):
"""
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'
-gis_lookups['overlaps_below'] = OverlapsBelowLookup
-
-
+@BaseSpatialField.register_lookup
class OverlapsAboveLookup(GISLookup):
"""
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'
-gis_lookups['overlaps_above'] = OverlapsAboveLookup
-
-
+@BaseSpatialField.register_lookup
class LeftLookup(GISLookup):
"""
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'
-gis_lookups['left'] = LeftLookup
-
-
+@BaseSpatialField.register_lookup
class RightLookup(GISLookup):
"""
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'
-gis_lookups['right'] = RightLookup
-
-
+@BaseSpatialField.register_lookup
class StrictlyBelowLookup(GISLookup):
"""
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'
-gis_lookups['strictly_below'] = StrictlyBelowLookup
-
-
+@BaseSpatialField.register_lookup
class StrictlyAboveLookup(GISLookup):
"""
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'
-gis_lookups['strictly_above'] = StrictlyAboveLookup
-
-
+@BaseSpatialField.register_lookup
class SameAsLookup(GISLookup):
"""
The "~=" operator is the "same as" operator. It tests actual geometric
@@ -204,17 +188,10 @@ class SameAsLookup(GISLookup):
lookup_name = 'same_as'
-gis_lookups['same_as'] = SameAsLookup
-
-
-class ExactLookup(SameAsLookup):
- # Alias of same_as
- lookup_name = 'exact'
-
-
-gis_lookups['exact'] = ExactLookup
+BaseSpatialField.register_lookup(SameAsLookup, 'exact')
+@BaseSpatialField.register_lookup
class BBContainsLookup(GISLookup):
"""
The 'bbcontains' operator returns true if A's bounding box completely contains
@@ -223,9 +200,7 @@ class BBContainsLookup(GISLookup):
lookup_name = 'bbcontains'
-gis_lookups['bbcontains'] = BBContainsLookup
-
-
+@BaseSpatialField.register_lookup
class BBOverlapsLookup(GISLookup):
"""
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'
-gis_lookups['bboverlaps'] = BBOverlapsLookup
-
-
+@BaseSpatialField.register_lookup
class ContainedLookup(GISLookup):
"""
The 'contained' operator returns true if A's bounding box is completely contained
@@ -244,69 +217,51 @@ class ContainedLookup(GISLookup):
lookup_name = 'contained'
-gis_lookups['contained'] = ContainedLookup
-
-
# ------------------
# Geometry functions
# ------------------
+@BaseSpatialField.register_lookup
class ContainsLookup(GISLookup):
lookup_name = 'contains'
-gis_lookups['contains'] = ContainsLookup
-
-
+@BaseSpatialField.register_lookup
class ContainsProperlyLookup(GISLookup):
lookup_name = 'contains_properly'
-gis_lookups['contains_properly'] = ContainsProperlyLookup
-
-
+@BaseSpatialField.register_lookup
class CoveredByLookup(GISLookup):
lookup_name = 'coveredby'
-gis_lookups['coveredby'] = CoveredByLookup
-
-
+@BaseSpatialField.register_lookup
class CoversLookup(GISLookup):
lookup_name = 'covers'
-gis_lookups['covers'] = CoversLookup
-
-
+@BaseSpatialField.register_lookup
class CrossesLookup(GISLookup):
lookup_name = 'crosses'
-gis_lookups['crosses'] = CrossesLookup
-
-
+@BaseSpatialField.register_lookup
class DisjointLookup(GISLookup):
lookup_name = 'disjoint'
-gis_lookups['disjoint'] = DisjointLookup
-
-
+@BaseSpatialField.register_lookup
class EqualsLookup(GISLookup):
lookup_name = 'equals'
-gis_lookups['equals'] = EqualsLookup
-
-
+@BaseSpatialField.register_lookup
class IntersectsLookup(GISLookup):
lookup_name = 'intersects'
-gis_lookups['intersects'] = IntersectsLookup
-
-
+@BaseSpatialField.register_lookup
class IsValidLookup(GISLookup):
lookup_name = 'isvalid'
sql_template = '%(func)s(%(lhs)s)'
@@ -322,16 +277,12 @@ class IsValidLookup(GISLookup):
return sql, params
-gis_lookups['isvalid'] = IsValidLookup
-
-
+@BaseSpatialField.register_lookup
class OverlapsLookup(GISLookup):
lookup_name = 'overlaps'
-gis_lookups['overlaps'] = OverlapsLookup
-
-
+@BaseSpatialField.register_lookup
class RelateLookup(GISLookup):
lookup_name = 'relate'
sql_template = '%(func)s(%(lhs)s, %(rhs)s, %%s)'
@@ -351,23 +302,16 @@ class RelateLookup(GISLookup):
return super().get_db_prep_lookup(value, connection)
-gis_lookups['relate'] = RelateLookup
-
-
+@BaseSpatialField.register_lookup
class TouchesLookup(GISLookup):
lookup_name = 'touches'
-gis_lookups['touches'] = TouchesLookup
-
-
+@BaseSpatialField.register_lookup
class WithinLookup(GISLookup):
lookup_name = 'within'
-gis_lookups['within'] = WithinLookup
-
-
class DistanceLookupBase(GISLookup):
distance = True
sql_template = '%(func)s(%(lhs)s, %(rhs)s) %(op)s %(value)s'
@@ -400,37 +344,27 @@ class DistanceLookupBase(GISLookup):
return (rhs, params)
+@BaseSpatialField.register_lookup
class DWithinLookup(DistanceLookupBase):
lookup_name = 'dwithin'
sql_template = '%(func)s(%(lhs)s, %(rhs)s, %%s)'
-gis_lookups['dwithin'] = DWithinLookup
-
-
+@BaseSpatialField.register_lookup
class DistanceGTLookup(DistanceLookupBase):
lookup_name = 'distance_gt'
-gis_lookups['distance_gt'] = DistanceGTLookup
-
-
+@BaseSpatialField.register_lookup
class DistanceGTELookup(DistanceLookupBase):
lookup_name = 'distance_gte'
-gis_lookups['distance_gte'] = DistanceGTELookup
-
-
+@BaseSpatialField.register_lookup
class DistanceLTLookup(DistanceLookupBase):
lookup_name = 'distance_lt'
-gis_lookups['distance_lt'] = DistanceLTLookup
-
-
+@BaseSpatialField.register_lookup
class DistanceLTELookup(DistanceLookupBase):
lookup_name = 'distance_lte'
-
-
-gis_lookups['distance_lte'] = DistanceLTELookup
diff --git a/tests/gis_tests/rasterapp/test_rasterfield.py b/tests/gis_tests/rasterapp/test_rasterfield.py
index e0a7ff2a5a..975b68cab0 100644
--- a/tests/gis_tests/rasterapp/test_rasterfield.py
+++ b/tests/gis_tests/rasterapp/test_rasterfield.py
@@ -1,9 +1,8 @@
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.lookups import (
- DistanceLookupBase, gis_lookups,
-)
+from django.contrib.gis.db.models.lookups import DistanceLookupBase, GISLookup
from django.contrib.gis.gdal import HAS_GDAL
from django.contrib.gis.geos import GEOSGeometry
from django.contrib.gis.measure import D
@@ -130,7 +129,9 @@ class RasterFieldTest(TransactionTestCase):
stx_pnt.transform(3086)
# 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.
combo_keys = [
field + name for field in [