summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2014-05-24 16:18:45 +0200
committerClaude Paroz <claude@2xlibre.net>2014-05-24 16:18:45 +0200
commit3caf957ed5eaa831a485abcb89f27266dbf3e82b (patch)
tree2e98680a261f357e54b079610efc21e768f24b89
parentb8fc167b32926e09d6d73eddc555343360f9c087 (diff)
Removed GeoWhereNode, obsoleted by GISLookup
-rw-r--r--django/contrib/gis/db/models/lookups.py45
-rw-r--r--django/contrib/gis/db/models/sql/__init__.py3
-rw-r--r--django/contrib/gis/db/models/sql/query.py11
-rw-r--r--django/contrib/gis/db/models/sql/where.py93
4 files changed, 49 insertions, 103 deletions
diff --git a/django/contrib/gis/db/models/lookups.py b/django/contrib/gis/db/models/lookups.py
index cad6c69000..8f803a73c1 100644
--- a/django/contrib/gis/db/models/lookups.py
+++ b/django/contrib/gis/db/models/lookups.py
@@ -1,10 +1,51 @@
+from django.db.models.constants import LOOKUP_SEP
+from django.db.models.fields import FieldDoesNotExist
from django.db.models.lookups import Lookup
from django.db.models.sql.expressions import SQLEvaluator
class GISLookup(Lookup):
+ @classmethod
+ def _check_geo_field(cls, opts, lookup):
+ """
+ Utility for checking the given lookup with the given model options.
+ The lookup is a string either specifying the geographic field, e.g.
+ 'point, 'the_geom', or a related lookup on a geographic field like
+ 'address__point'.
+
+ If a GeometryField exists according to the given lookup on the model
+ options, it will be returned. Otherwise returns None.
+ """
+ from django.contrib.gis.db.models.fields import GeometryField
+ # This takes into account the situation where the lookup is a
+ # lookup to a related geographic field, e.g., 'address__point'.
+ field_list = lookup.split(LOOKUP_SEP)
+
+ # Reversing so list operates like a queue of related lookups,
+ # and popping the top lookup.
+ field_list.reverse()
+ fld_name = field_list.pop()
+
+ try:
+ geo_fld = opts.get_field(fld_name)
+ # If the field list is still around, then it means that the
+ # lookup was for a geometry field across a relationship --
+ # thus we keep on getting the related model options and the
+ # model field associated with the next field in the list
+ # until there's no more left.
+ while len(field_list):
+ opts = geo_fld.rel.to._meta
+ geo_fld = opts.get_field(field_list.pop())
+ except (FieldDoesNotExist, AttributeError):
+ return False
+
+ # Finally, make sure we got a Geographic field and return.
+ if isinstance(geo_fld, GeometryField):
+ return geo_fld
+ else:
+ return False
+
def as_sql(self, qn, connection):
- from django.contrib.gis.db.models.sql import GeoWhereNode
# We use the same approach as was used by GeoWhereNode. It would
# be a good idea to upgrade GIS to use similar code that is used
# for other lookups.
@@ -12,7 +53,7 @@ class GISLookup(Lookup):
# Make sure the F Expression destination field exists, and
# set an `srid` attribute with the same as that of the
# destination.
- geo_fld = GeoWhereNode._check_geo_field(self.rhs.opts, self.rhs.expression.name)
+ geo_fld = self._check_geo_field(self.rhs.opts, self.rhs.expression.name)
if not geo_fld:
raise ValueError('No geographic field found in expression.')
self.rhs.srid = geo_fld.srid
diff --git a/django/contrib/gis/db/models/sql/__init__.py b/django/contrib/gis/db/models/sql/__init__.py
index a7d15dab63..cde4c2d5e6 100644
--- a/django/contrib/gis/db/models/sql/__init__.py
+++ b/django/contrib/gis/db/models/sql/__init__.py
@@ -1,7 +1,6 @@
from django.contrib.gis.db.models.sql.conversion import AreaField, DistanceField, GeomField
from django.contrib.gis.db.models.sql.query import GeoQuery
-from django.contrib.gis.db.models.sql.where import GeoWhereNode
__all__ = [
- 'AreaField', 'DistanceField', 'GeomField', 'GeoQuery', 'GeoWhereNode',
+ 'AreaField', 'DistanceField', 'GeomField', 'GeoQuery',
]
diff --git a/django/contrib/gis/db/models/sql/query.py b/django/contrib/gis/db/models/sql/query.py
index f3fa1f6322..9aec3a65bc 100644
--- a/django/contrib/gis/db/models/sql/query.py
+++ b/django/contrib/gis/db/models/sql/query.py
@@ -3,9 +3,9 @@ from django.db.models.query import sql
from django.contrib.gis.db.models.constants import ALL_TERMS
from django.contrib.gis.db.models.fields import GeometryField
+from django.contrib.gis.db.models.lookups import GISLookup
from django.contrib.gis.db.models.sql import aggregates as gis_aggregates
from django.contrib.gis.db.models.sql.conversion import AreaField, DistanceField, GeomField
-from django.contrib.gis.db.models.sql.where import GeoWhereNode
from django.contrib.gis.geometry.backend import Geometry
from django.contrib.gis.measure import Area, Distance
@@ -21,11 +21,10 @@ class GeoQuery(sql.Query):
compiler = 'GeoSQLCompiler'
#### Methods overridden from the base Query class ####
- def __init__(self, model, where=GeoWhereNode):
- super(GeoQuery, self).__init__(model, where)
+ def __init__(self, model):
+ super(GeoQuery, self).__init__(model) #, where)
# The following attributes are customized for the GeoQuerySet.
- # The GeoWhereNode and SpatialBackend classes contain backend-specific
- # routines and functions.
+ # The SpatialBackend classes contain backend-specific routines and functions.
self.custom_select = {}
self.transformed_srid = None
self.extra_select_fields = {}
@@ -108,4 +107,4 @@ class GeoQuery(sql.Query):
else:
# Otherwise, check by the given field name -- which may be
# a lookup to a _related_ geographic field.
- return GeoWhereNode._check_geo_field(self.model._meta, field_name)
+ return GISLookup._check_geo_field(self.model._meta, field_name)
diff --git a/django/contrib/gis/db/models/sql/where.py b/django/contrib/gis/db/models/sql/where.py
deleted file mode 100644
index 1e750ebd89..0000000000
--- a/django/contrib/gis/db/models/sql/where.py
+++ /dev/null
@@ -1,93 +0,0 @@
-from django.db.models.constants import LOOKUP_SEP
-from django.db.models.fields import FieldDoesNotExist
-from django.db.models.sql.expressions import SQLEvaluator
-from django.db.models.sql.where import Constraint, WhereNode
-from django.contrib.gis.db.models.fields import GeometryField
-
-
-class GeoConstraint(Constraint):
- """
- This subclass overrides `process` to better handle geographic SQL
- construction.
- """
- def __init__(self, init_constraint):
- self.alias = init_constraint.alias
- self.col = init_constraint.col
- self.field = init_constraint.field
-
- def process(self, lookup_type, value, connection):
- if isinstance(value, SQLEvaluator):
- # Make sure the F Expression destination field exists, and
- # set an `srid` attribute with the same as that of the
- # destination.
- geo_fld = GeoWhereNode._check_geo_field(value.opts, value.expression.name)
- if not geo_fld:
- raise ValueError('No geographic field found in expression.')
- value.srid = geo_fld.srid
- db_type = self.field.db_type(connection=connection)
- params = self.field.get_db_prep_lookup(lookup_type, value, connection=connection)
- return (self.alias, self.col, db_type), params
-
-
-class GeoWhereNode(WhereNode):
- """
- Used to represent the SQL where-clause for spatial databases --
- these are tied to the GeoQuery class that created it.
- """
-
- def _prepare_data(self, data):
- if isinstance(data, (list, tuple)):
- obj, lookup_type, value = data
- if (isinstance(obj, Constraint) and
- isinstance(obj.field, GeometryField)):
- data = (GeoConstraint(obj), lookup_type, value)
- return super(GeoWhereNode, self)._prepare_data(data)
-
- def make_atom(self, child, qn, connection):
- lvalue, lookup_type, value_annot, params_or_value = child
- if isinstance(lvalue, GeoConstraint):
- data, params = lvalue.process(lookup_type, params_or_value, connection)
- spatial_sql, spatial_params = connection.ops.spatial_lookup_sql(
- data, lookup_type, params_or_value, lvalue.field, qn)
- return spatial_sql, spatial_params + params
- else:
- return super(GeoWhereNode, self).make_atom(child, qn, connection)
-
- @classmethod
- def _check_geo_field(cls, opts, lookup):
- """
- Utility for checking the given lookup with the given model options.
- The lookup is a string either specifying the geographic field, e.g.
- 'point, 'the_geom', or a related lookup on a geographic field like
- 'address__point'.
-
- If a GeometryField exists according to the given lookup on the model
- options, it will be returned. Otherwise returns None.
- """
- # This takes into account the situation where the lookup is a
- # lookup to a related geographic field, e.g., 'address__point'.
- field_list = lookup.split(LOOKUP_SEP)
-
- # Reversing so list operates like a queue of related lookups,
- # and popping the top lookup.
- field_list.reverse()
- fld_name = field_list.pop()
-
- try:
- geo_fld = opts.get_field(fld_name)
- # If the field list is still around, then it means that the
- # lookup was for a geometry field across a relationship --
- # thus we keep on getting the related model options and the
- # model field associated with the next field in the list
- # until there's no more left.
- while len(field_list):
- opts = geo_fld.rel.to._meta
- geo_fld = opts.get_field(field_list.pop())
- except (FieldDoesNotExist, AttributeError):
- return False
-
- # Finally, make sure we got a Geographic field and return.
- if isinstance(geo_fld, GeometryField):
- return geo_fld
- else:
- return False