summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/contrib/gis/db/backends/base/features.py22
-rw-r--r--django/contrib/gis/db/backends/oracle/models.py1
-rw-r--r--django/contrib/gis/db/models/__init__.py3
-rw-r--r--django/contrib/gis/db/models/fields.py21
-rw-r--r--django/contrib/gis/db/models/manager.py26
-rw-r--r--django/contrib/gis/db/models/query.py727
-rw-r--r--docs/ref/contrib/gis/geoquerysets.txt595
-rw-r--r--docs/ref/contrib/gis/model-api.txt16
-rw-r--r--docs/ref/models/querysets.txt9
-rw-r--r--docs/releases/1.2.txt8
-rw-r--r--docs/releases/2.0.txt2
-rw-r--r--tests/gis_tests/distapp/models.py2
-rw-r--r--tests/gis_tests/distapp/tests.py215
-rw-r--r--tests/gis_tests/geo3d/models.py2
-rw-r--r--tests/gis_tests/geo3d/tests.py105
-rw-r--r--tests/gis_tests/geoapp/models.py2
-rw-r--r--tests/gis_tests/geoapp/test_functions.py2
-rw-r--r--tests/gis_tests/geoapp/test_regress.py2
-rw-r--r--tests/gis_tests/geoapp/tests.py380
-rw-r--r--tests/gis_tests/geogapp/models.py2
-rw-r--r--tests/gis_tests/geogapp/tests.py29
-rw-r--r--tests/gis_tests/relatedapp/models.py3
-rw-r--r--tests/gis_tests/relatedapp/tests.py33
-rw-r--r--tests/managers_regress/tests.py13
-rwxr-xr-xtests/runtests.py6
25 files changed, 32 insertions, 2194 deletions
diff --git a/django/contrib/gis/db/backends/base/features.py b/django/contrib/gis/db/backends/base/features.py
index 166495a6cc..5ca2881330 100644
--- a/django/contrib/gis/db/backends/base/features.py
+++ b/django/contrib/gis/db/backends/base/features.py
@@ -1,5 +1,4 @@
import re
-from functools import partial
from django.contrib.gis.db.models import aggregates
@@ -71,17 +70,6 @@ class BaseSpatialFeatures(object):
def supports_isvalid_lookup(self):
return 'isvalid' in self.connection.ops.gis_operators
- # For each of those methods, the class will have a property named
- # `has_<name>_method` (defined in __init__) which accesses connection.ops
- # to determine GIS method availability.
- geoqueryset_methods = (
- 'area', 'bounding_circle', 'centroid', 'difference', 'distance',
- 'distance_spheroid', 'envelope', 'force_rhr', 'geohash', 'gml',
- 'intersection', 'kml', 'length', 'mem_size', 'num_geom', 'num_points',
- 'perimeter', 'point_on_surface', 'reverse', 'scale', 'snap_to_grid',
- 'svg', 'sym_difference', 'transform', 'translate', 'union', 'unionagg',
- )
-
# Is the aggregate supported by the database?
@property
def supports_collect_aggr(self):
@@ -99,19 +87,9 @@ class BaseSpatialFeatures(object):
def supports_union_aggr(self):
return aggregates.Union not in self.connection.ops.disallowed_aggregates
- def __init__(self, *args):
- super(BaseSpatialFeatures, self).__init__(*args)
- for method in self.geoqueryset_methods:
- # Add dynamically properties for each GQS method, e.g. has_force_rhr_method, etc.
- setattr(self.__class__, 'has_%s_method' % method,
- property(partial(BaseSpatialFeatures.has_ops_method, method=method)))
-
def __getattr__(self, name):
m = re.match(r'has_(\w*)_function$', name)
if m:
func_name = m.group(1)
return func_name not in self.connection.ops.unsupported_functions
raise AttributeError
-
- def has_ops_method(self, method):
- return getattr(self.connection.ops, method, False)
diff --git a/django/contrib/gis/db/backends/oracle/models.py b/django/contrib/gis/db/backends/oracle/models.py
index 02dcf212ea..e1bf49050b 100644
--- a/django/contrib/gis/db/backends/oracle/models.py
+++ b/django/contrib/gis/db/backends/oracle/models.py
@@ -55,7 +55,6 @@ class OracleSpatialRefSys(models.Model, SpatialRefSysMixin):
# Optional geometry representing the bounds of this coordinate
# system. By default, all are NULL in the table.
cs_bounds = models.PolygonField(null=True)
- objects = models.GeoManager()
class Meta:
app_label = 'gis'
diff --git a/django/contrib/gis/db/models/__init__.py b/django/contrib/gis/db/models/__init__.py
index 84f84d32b0..5f6c2374a7 100644
--- a/django/contrib/gis/db/models/__init__.py
+++ b/django/contrib/gis/db/models/__init__.py
@@ -7,11 +7,10 @@ from django.contrib.gis.db.models.fields import (
MultiLineStringField, MultiPointField, MultiPolygonField, PointField,
PolygonField, RasterField,
)
-from django.contrib.gis.db.models.manager import GeoManager
__all__ = models_all + aggregates_all
__all__ += [
'GeometryCollectionField', 'GeometryField', 'LineStringField',
'MultiLineStringField', 'MultiPointField', 'MultiPolygonField', 'PointField',
- 'PolygonField', 'RasterField', 'GeoManager',
+ 'PolygonField', 'RasterField',
]
diff --git a/django/contrib/gis/db/models/fields.py b/django/contrib/gis/db/models/fields.py
index 2fd74da632..215a17b6b5 100644
--- a/django/contrib/gis/db/models/fields.py
+++ b/django/contrib/gis/db/models/fields.py
@@ -346,27 +346,6 @@ class GeometryField(GeoSelectFormatMixin, BaseSpatialField):
defaults['widget'] = forms.Textarea
return super(GeometryField, self).formfield(**defaults)
- def _get_db_prep_lookup(self, lookup_type, value, connection):
- """
- Prepare for the database lookup, and return any spatial parameters
- necessary for the query. This includes wrapping any geometry
- parameters with a backend-specific adapter and formatting any distance
- parameters into the correct units for the coordinate system of the
- field.
-
- Only used by the deprecated GeoQuerySet and to be
- RemovedInDjango20Warning.
- """
- # Populating the parameters list, and wrapping the Geometry
- # with the Adapter of the spatial backend.
- if isinstance(value, (tuple, list)):
- params = [connection.ops.Adapter(value[0])]
- # Getting the distance parameter in the units of the field.
- params += self.get_distance(value[1:], lookup_type, connection)
- else:
- params = [connection.ops.Adapter(value)]
- return params
-
# The OpenGIS Geometry Type Fields
class PointField(GeometryField):
diff --git a/django/contrib/gis/db/models/manager.py b/django/contrib/gis/db/models/manager.py
deleted file mode 100644
index 44f0140090..0000000000
--- a/django/contrib/gis/db/models/manager.py
+++ /dev/null
@@ -1,26 +0,0 @@
-import warnings
-
-from django.contrib.gis.db.models.query import GeoQuerySet
-from django.db.models.manager import Manager
-from django.utils.deprecation import RemovedInDjango20Warning
-
-
-class GeoManager(Manager.from_queryset(GeoQuerySet)):
- "Overrides Manager to return Geographic QuerySets."
-
- # This manager should be used for queries on related fields
- # so that geometry columns on Oracle and MySQL are selected
- # properly.
- use_for_related_fields = True
-
- # No need to bother users with the use_for_related_fields
- # deprecation for this manager which is itself deprecated.
- silence_use_for_related_fields_deprecation = True
-
- def __init__(self, *args, **kwargs):
- warnings.warn(
- "The GeoManager class is deprecated. Simply use a normal manager "
- "once you have replaced all calls to GeoQuerySet methods by annotations.",
- RemovedInDjango20Warning, stacklevel=2
- )
- super(GeoManager, self).__init__(*args, **kwargs)
diff --git a/django/contrib/gis/db/models/query.py b/django/contrib/gis/db/models/query.py
deleted file mode 100644
index d1933721b6..0000000000
--- a/django/contrib/gis/db/models/query.py
+++ /dev/null
@@ -1,727 +0,0 @@
-import warnings
-
-from django.contrib.gis.db.models.fields import (
- GeometryField, LineStringField, PointField, get_srid_info,
-)
-from django.contrib.gis.db.models.lookups import GISLookup
-from django.contrib.gis.db.models.sql import (
- AreaField, DistanceField, GeomField, GMLField,
-)
-from django.contrib.gis.geometry.backend import Geometry
-from django.contrib.gis.measure import Area, Distance
-from django.db import connections
-from django.db.models.constants import LOOKUP_SEP
-from django.db.models.expressions import RawSQL
-from django.db.models.fields import Field
-from django.db.models.query import QuerySet
-from django.utils import six
-from django.utils.deprecation import RemovedInDjango20Warning
-
-
-class GeoQuerySet(QuerySet):
- "The Geographic QuerySet."
-
- # ### GeoQuerySet Methods ###
- def area(self, tolerance=0.05, **kwargs):
- """
- Returns the area of the geographic field in an `area` attribute on
- each element of this GeoQuerySet.
- """
- # Performing setup here rather than in `_spatial_attribute` so that
- # we can get the units for `AreaField`.
- procedure_args, geo_field = self._spatial_setup(
- 'area', field_name=kwargs.get('field_name'))
- s = {'procedure_args': procedure_args,
- 'geo_field': geo_field,
- 'setup': False,
- }
- connection = connections[self.db]
- backend = connection.ops
- if backend.oracle:
- s['procedure_fmt'] = '%(geo_col)s,%(tolerance)s'
- s['procedure_args']['tolerance'] = tolerance
- s['select_field'] = AreaField('sq_m') # Oracle returns area in units of meters.
- elif backend.postgis or backend.spatialite:
- if backend.geography:
- # Geography fields support area calculation, returns square meters.
- s['select_field'] = AreaField('sq_m')
- elif not geo_field.geodetic(connection):
- # Getting the area units of the geographic field.
- s['select_field'] = AreaField(Area.unit_attname(geo_field.units_name(connection)))
- else:
- # TODO: Do we want to support raw number areas for geodetic fields?
- raise Exception('Area on geodetic coordinate systems not supported.')
- return self._spatial_attribute('area', s, **kwargs)
-
- def centroid(self, **kwargs):
- """
- Returns the centroid of the geographic field in a `centroid`
- attribute on each element of this GeoQuerySet.
- """
- return self._geom_attribute('centroid', **kwargs)
-
- def difference(self, geom, **kwargs):
- """
- Returns the spatial difference of the geographic field in a `difference`
- attribute on each element of this GeoQuerySet.
- """
- return self._geomset_attribute('difference', geom, **kwargs)
-
- def distance(self, geom, **kwargs):
- """
- Returns the distance from the given geographic field name to the
- given geometry in a `distance` attribute on each element of the
- GeoQuerySet.
-
- Keyword Arguments:
- `spheroid` => If the geometry field is geodetic and PostGIS is
- the spatial database, then the more accurate
- spheroid calculation will be used instead of the
- quicker sphere calculation.
-
- `tolerance` => Used only for Oracle. The tolerance is
- in meters -- a default of 5 centimeters (0.05)
- is used.
- """
- return self._distance_attribute('distance', geom, **kwargs)
-
- def envelope(self, **kwargs):
- """
- Returns a Geometry representing the bounding box of the
- Geometry field in an `envelope` attribute on each element of
- the GeoQuerySet.
- """
- return self._geom_attribute('envelope', **kwargs)
-
- def force_rhr(self, **kwargs):
- """
- Returns a modified version of the Polygon/MultiPolygon in which
- all of the vertices follow the Right-Hand-Rule. By default,
- this is attached as the `force_rhr` attribute on each element
- of the GeoQuerySet.
- """
- return self._geom_attribute('force_rhr', **kwargs)
-
- def geojson(self, precision=8, crs=False, bbox=False, **kwargs):
- """
- Returns a GeoJSON representation of the geometry field in a `geojson`
- attribute on each element of the GeoQuerySet.
-
- The `crs` and `bbox` keywords may be set to True if the user wants
- the coordinate reference system and the bounding box to be included
- in the GeoJSON representation of the geometry.
- """
- backend = connections[self.db].ops
- if not backend.geojson:
- raise NotImplementedError('Only PostGIS and SpatiaLite support GeoJSON serialization.')
-
- if not isinstance(precision, six.integer_types):
- raise TypeError('Precision keyword must be set with an integer.')
-
- options = 0
- if crs and bbox:
- options = 3
- elif bbox:
- options = 1
- elif crs:
- options = 2
- s = {'desc': 'GeoJSON',
- 'procedure_args': {'precision': precision, 'options': options},
- 'procedure_fmt': '%(geo_col)s,%(precision)s,%(options)s',
- }
- return self._spatial_attribute('geojson', s, **kwargs)
-
- def geohash(self, precision=20, **kwargs):
- """
- Returns a GeoHash representation of the given field in a `geohash`
- attribute on each element of the GeoQuerySet.
-
- The `precision` keyword may be used to custom the number of
- _characters_ used in the output GeoHash, the default is 20.
- """
- s = {'desc': 'GeoHash',
- 'procedure_args': {'precision': precision},
- 'procedure_fmt': '%(geo_col)s,%(precision)s',
- }
- return self._spatial_attribute('geohash', s, **kwargs)
-
- def gml(self, precision=8, version=2, **kwargs):
- """
- Returns GML representation of the given field in a `gml` attribute
- on each element of the GeoQuerySet.
- """
- backend = connections[self.db].ops
- s = {'desc': 'GML', 'procedure_args': {'precision': precision}}
- if backend.postgis:
- s['procedure_fmt'] = '%(version)s,%(geo_col)s,%(precision)s'
- s['procedure_args'] = {'precision': precision, 'version': version}
- if backend.oracle:
- s['select_field'] = GMLField()
-
- return self._spatial_attribute('gml', s, **kwargs)
-
- def intersection(self, geom, **kwargs):
- """
- Returns the spatial intersection of the Geometry field in
- an `intersection` attribute on each element of this
- GeoQuerySet.
- """
- return self._geomset_attribute('intersection', geom, **kwargs)
-
- def kml(self, **kwargs):
- """
- Returns KML representation of the geometry field in a `kml`
- attribute on each element of this GeoQuerySet.
- """
- s = {'desc': 'KML',
- 'procedure_fmt': '%(geo_col)s,%(precision)s',
- 'procedure_args': {'precision': kwargs.pop('precision', 8)},
- }
- return self._spatial_attribute('kml', s, **kwargs)
-
- def length(self, **kwargs):
- """
- Returns the length of the geometry field as a `Distance` object
- stored in a `length` attribute on each element of this GeoQuerySet.
- """
- return self._distance_attribute('length', None, **kwargs)
-
- def mem_size(self, **kwargs):
- """
- Returns the memory size (number of bytes) that the geometry field takes
- in a `mem_size` attribute on each element of this GeoQuerySet.
- """
- return self._spatial_attribute('mem_size', {}, **kwargs)
-
- def num_geom(self, **kwargs):
- """
- Returns the number of geometries if the field is a
- GeometryCollection or Multi* Field in a `num_geom`
- attribute on each element of this GeoQuerySet; otherwise
- the sets with None.
- """
- return self._spatial_attribute('num_geom', {}, **kwargs)
-
- def num_points(self, **kwargs):
- """
- Returns the number of points in the first linestring in the
- Geometry field in a `num_points` attribute on each element of
- this GeoQuerySet; otherwise sets with None.
- """
- return self._spatial_attribute('num_points', {}, **kwargs)
-
- def perimeter(self, **kwargs):
- """
- Returns the perimeter of the geometry field as a `Distance` object
- stored in a `perimeter` attribute on each element of this GeoQuerySet.
- """
- return self._distance_attribute('perimeter', None, **kwargs)
-
- def point_on_surface(self, **kwargs):
- """
- Returns a Point geometry guaranteed to lie on the surface of the
- Geometry field in a `point_on_surface` attribute on each element
- of this GeoQuerySet; otherwise sets with None.
- """
- return self._geom_attribute('point_on_surface', **kwargs)
-
- def reverse_geom(self, **kwargs):
- """
- Reverses the coordinate order of the geometry, and attaches as a
- `reverse` attribute on each element of this GeoQuerySet.
- """
- s = {'select_field': GeomField()}
- kwargs.setdefault('model_att', 'reverse_geom')
- if connections[self.db].ops.oracle:
- s['geo_field_type'] = LineStringField
- return self._spatial_attribute('reverse', s, **kwargs)
-
- def scale(self, x, y, z=0.0, **kwargs):
- """
- Scales the geometry to a new size by multiplying the ordinates
- with the given x,y,z scale factors.
- """
- if connections[self.db].ops.spatialite:
- if z != 0.0:
- raise NotImplementedError('SpatiaLite does not support 3D scaling.')
- s = {'procedure_fmt': '%(geo_col)s,%(x)s,%(y)s',
- 'procedure_args': {'x': x, 'y': y},
- 'select_field': GeomField(),
- }
- else:
- s = {'procedure_fmt': '%(geo_col)s,%(x)s,%(y)s,%(z)s',
- 'procedure_args': {'x': x, 'y': y, 'z': z},
- 'select_field': GeomField(),
- }
- return self._spatial_attribute('scale', s, **kwargs)
-
- def snap_to_grid(self, *args, **kwargs):
- """
- Snap all points of the input geometry to the grid. How the
- geometry is snapped to the grid depends on how many arguments
- were given:
- - 1 argument : A single size to snap both the X and Y grids to.
- - 2 arguments: X and Y sizes to snap the grid to.
- - 4 arguments: X, Y sizes and the X, Y origins.
- """
- if False in [isinstance(arg, (float,) + six.integer_types) for arg in args]:
- raise TypeError('Size argument(s) for the grid must be a float or integer values.')
-
- nargs = len(args)
- if nargs == 1:
- size = args[0]
- procedure_fmt = '%(geo_col)s,%(size)s'
- procedure_args = {'size': size}
- elif nargs == 2:
- xsize, ysize = args
- procedure_fmt = '%(geo_col)s,%(xsize)s,%(ysize)s'
- procedure_args = {'xsize': xsize, 'ysize': ysize}
- elif nargs == 4:
- xsize, ysize, xorigin, yorigin = args
- procedure_fmt = '%(geo_col)s,%(xorigin)s,%(yorigin)s,%(xsize)s,%(ysize)s'
- procedure_args = {'xsize': xsize, 'ysize': ysize,
- 'xorigin': xorigin, 'yorigin': yorigin}
- else:
- raise ValueError('Must provide 1, 2, or 4 arguments to `snap_to_grid`.')
-
- s = {'procedure_fmt': procedure_fmt,
- 'procedure_args': procedure_args,
- 'select_field': GeomField(),
- }
-
- return self._spatial_attribute('snap_to_grid', s, **kwargs)
-
- def svg(self, relative=False, precision=8, **kwargs):
- """
- Returns SVG representation of the geographic field in a `svg`
- attribute on each element of this GeoQuerySet.
-
- Keyword Arguments:
- `relative` => If set to True, this will evaluate the path in
- terms of relative moves (rather than absolute).
-
- `precision` => May be used to set the maximum number of decimal
- digits used in output (defaults to 8).
- """
- relative = int(bool(relative))
- if not isinstance(precision, six.integer_types):
- raise TypeError('SVG precision keyword argument must be an integer.')
- s = {
- 'desc': 'SVG',
- 'procedure_fmt': '%(geo_col)s,%(rel)s,%(precision)s',
- 'procedure_args': {
- 'rel': relative,
- 'precision': precision,
- }
- }
- return self._spatial_attribute('svg', s, **kwargs)
-
- def sym_difference(self, geom, **kwargs):
- """
- Returns the symmetric difference of the geographic field in a
- `sym_difference` attribute on each element of this GeoQuerySet.
- """
- return self._geomset_attribute('sym_difference', geom, **kwargs)
-
- def translate(self, x, y, z=0.0, **kwargs):
- """
- Translates the geometry to a new location using the given numeric
- parameters as offsets.
- """
- if connections[self.db].ops.spatialite:
- if z != 0.0:
- raise NotImplementedError('SpatiaLite does not support 3D translation.')
- s = {'procedure_fmt': '%(geo_col)s,%(x)s,%(y)s',
- 'procedure_args': {'x': x, 'y': y},
- 'select_field': GeomField(),
- }
- else:
- s = {'procedure_fmt': '%(geo_col)s,%(x)s,%(y)s,%(z)s',
- 'procedure_args': {'x': x, 'y': y, 'z': z},
- 'select_field': GeomField(),
- }
- return self._spatial_attribute('translate', s, **kwargs)
-
- def transform(self, srid=4326, **kwargs):
- """
- Transforms the given geometry field to the given SRID. If no SRID is
- provided, the transformation will default to using 4326 (WGS84).
- """
- if not isinstance(srid, six.integer_types):
- raise TypeError('An integer SRID must be provided.')
- field_name = kwargs.get('field_name')
- self._spatial_setup('transform', field_name=field_name)
- self.query.add_context('transformed_srid', srid)
- return self._clone()
-
- def union(self, geom, **kwargs):
- """
- Returns the union of the geographic field with the given
- Geometry in a `union` attribute on each element of this GeoQuerySet.
- """
- return self._geomset_attribute('union', geom, **kwargs)
-
- # ### Private API -- Abstracted DRY routines. ###
- def _spatial_setup(self, att, desc=None, field_name=None, geo_field_type=None):
- """
- Performs set up for executing the spatial function.
- """
- # Does the spatial backend support this?
- connection = connections[self.db]
- func = getattr(connection.ops, att, False)
- if desc is None:
- desc = att
- if not func:
- raise NotImplementedError('%s stored procedure not available on '
- 'the %s backend.' %
- (desc, connection.ops.name))
-
- # Initializing the procedure arguments.
- procedure_args = {'function': func}
-
- # Is there a geographic field in the model to perform this
- # operation on?
- geo_field = self._geo_field(field_name)
- if not geo_field:
- raise TypeError('%s output only available on GeometryFields.' % func)
-
- # If the `geo_field_type` keyword was used, then enforce that
- # type limitation.
- if geo_field_type is not None and not isinstance(geo_field, geo_field_type):
- raise TypeError('"%s" stored procedures may only be called on %ss.' % (func, geo_field_type.__name__))
-
- # Setting the procedure args.
- procedure_args['geo_col'] = self._geocol_select(geo_field, field_name)
-
- return procedure_args, geo_field
-
- def _spatial_attribute(self, att, settings, field_name=None, model_att=None):
- """
- DRY routine for calling a spatial stored procedure on a geometry column
- and attaching its output as an attribute of the model.
-
- Arguments:
- att:
- The name of the spatial attribute that holds the spatial
- SQL function to call.
-
- settings:
- Dictionary of internal settings to customize for the spatial procedure.
-
- Public Keyword Arguments:
-
- field_name:
- The name of the geographic field to call the spatial
- function on. May also be a lookup to a geometry field
- as part of a foreign key relation.
-
- model_att:
- The name of the model attribute to attach the output of
- the spatial function to.
- """
- warnings.warn(
- "The %s GeoQuerySet method is deprecated. See GeoDjango Functions "
- "documentation to find the expression-based replacement." % att,
- RemovedInDjango20Warning, stacklevel=2
- )
- # Default settings.
- settings.setdefault('desc', None)
- settings.setdefault('geom_args', ())
- settings.setdefault('geom_field', None)
- settings.setdefault('procedure_args', {})
- settings.setdefault('procedure_fmt', '%(geo_col)s')
- settings.setdefault('select_params', [])
-
- connection = connections[self.db]
-
- # Performing setup for the spatial column, unless told not to.
- if settings.get('setup', True):
- default_args, geo_field = self._spatial_setup(
- att, desc=settings['desc'], field_name=field_name,
- geo_field_type=settings.get('geo_field_type'))
- for k, v in six.iteritems(default_args):
- settings['procedure_args'].setdefault(k, v)
- else:
- geo_field = settings['geo_field']
-
- # The attribute to attach to the model.
- if not isinstance(model_att, six.string_types):
- model_att = att
-
- # Special handling for any argument that is a geometry.
- for name in settings['geom_args']:
- # Using the field's get_placeholder() routine to get any needed
- # transformation SQL.
- geom = geo_field.get_prep_value(settings['procedure_args'][name])
- params = geo_field._get_db_prep_lookup('contains', geom, connection=connection)
- geom_placeholder = geo_field.get_placeholder(geom, None, connection)
-
- # Replacing the procedure format with that of any needed
- # transformation SQL.
- old_fmt = '%%(%s)s' % name
- new_fmt = geom_placeholder % '%%s'
- settings['procedure_fmt'] = settings['procedure_fmt'].replace(old_fmt, new_fmt)
- settings['select_params'].extend(params)
-
- # Getting the format for the stored procedure.
- fmt = '%%(function)s(%s)' % settings['procedure_fmt']
-
- # If the result of this function needs to be converted.
- if settings.get('select_field'):
- select_field = settings['select_field']
- if connection.ops.oracle:
- select_field.empty_strings_allowed = False
- else:
- select_field = Field()
-
- # Finally, setting the extra selection attribute with
- # the format string expanded with the stored procedure
- # arguments.
- self.query.add_annotation(
- RawSQL(fmt % settings['procedure_args'], settings['select_params'], select_field),
- model_att)
- return self
-
- def _distance_attribute(self, func, geom=None, tolerance=0.05, spheroid=False, **kwargs):
- """
- DRY routine for GeoQuerySet distance attribute routines.
- """
- # Setting up the distance procedure arguments.
- procedure_args, geo_field = self._spatial_setup(func, field_name=kwargs.get('field_name'))
-
- # If geodetic defaulting distance attribute to meters (Oracle and
- # PostGIS spherical distances return meters). Otherwise, use the
- # units of the geometry field.
- connection = connections[self.db]
- geodetic = geo_field.geodetic(connection)
- geography = geo_field.geography
-
- if geodetic:
- dist_att = 'm'
- else:
- dist_att = Distance.unit_attname(geo_field.units_name(connection))
-
- # Shortcut booleans for what distance function we're using and
- # whether the geometry field is 3D.
- distance = func == 'distance'
- length = func == 'length'
- perimeter = func == 'perimeter'
- if not (distance or length or perimeter):
- raise ValueError('Unknown distance function: %s' % func)
- geom_3d = geo_field.dim == 3
-
- # The field's _get_db_prep_lookup() is used to get any
- # extra distance parameters. Here we set up the
- # parameters that will be passed in to field's function.
- lookup_params = [geom or 'POINT (0 0)', 0]
-
- # Getting the spatial backend operations.
- backend = connection.ops
-
- # If the spheroid calculation is desired, either by the `spheroid`
- # keyword or when calculating the length of geodetic field, make
- # sure the 'spheroid' distance setting string is passed in so we
- # get the correct spatial stored procedure.
- if spheroid or (backend.postgis and geodetic and
- (not geography) and length):
- lookup_params.append('spheroid')
- lookup_params = geo_field.get_prep_value(lookup_params)
- params = geo_field._get_db_prep_lookup('distance_lte', lookup_params, connection=connection)
-
- # The `geom_args` flag is set to true if a geometry parameter was
- # passed in.
- geom_args = bool(geom)
-
- if backend.oracle:
- if distance:
- procedure_fmt = '%(geo_col)s,%(geom)s,%(tolerance)s'
- elif length or perimeter:
- procedure_fmt = '%(geo_col)s,%(tolerance)s'
- procedure_args['tolerance'] = tolerance
- else:
- # Getting whether this field is in units of degrees since the field may have
- # been transformed via the `transform` GeoQuerySet method.
- srid = self.query.get_context('transformed_srid')
- if srid:
- u, unit_name, s = get_srid_info(srid, connection)
- geodetic = unit_name.lower() in geo_field.geodetic_units
-
- if geodetic and (not connection.features.supports_distance_geodetic or connection.ops.spatialite):
- raise ValueError(
- 'This database does not support linear distance '
- 'calculations on geodetic coordinate systems.'
- )
-
- if distance:
- if srid:
- # Setting the `geom_args` flag to false because we want to handle
- # transformation SQL here, rather than the way done by default
- # (which will transform to the original SRID of the field rather
- # than to what was transformed to).
- geom_args = False
- procedure_fmt = '%s(%%(geo_col)s, %s)' % (backend.transform, srid)
- if geom.srid is None or geom.srid == srid:
- # If the geom parameter srid is None, it is assumed the coordinates
- # are in the transformed units. A placeholder is used for the
- # geometry parameter. `GeomFromText` constructor is also needed
- # to wrap geom placeholder for SpatiaLite.
- if backend.spatialite:
- procedure_fmt += ', %s(%%%%s, %s)' % (backend.from_text, srid)
- else:
- procedure_fmt += ', %%s'
- else:
- # We need to transform the geom to the srid specified in `transform()`,
- # so wrapping the geometry placeholder in transformation SQL.
- # SpatiaLite also needs geometry placeholder wrapped in `GeomFromText`
- # constructor.
- if backend.spatialite:
- procedure_fmt += (', %s(%s(%%%%s, %s), %s)' % (
- backend.transform, backend.from_text,
- geom.srid, srid))
- else:
- procedure_fmt += ', %s(%%%%s, %s)' % (backend.transform, srid)
- else:
- # `transform()` was not used on this GeoQuerySet.
- procedure_fmt = '%(geo_col)s,%(geom)s'
-
- if not geography and geodetic:
- # Spherical distance calculation is needed (because the geographic
- # field is geodetic). However, the PostGIS ST_distance_sphere/spheroid()
- # procedures may only do queries from point columns to point geometries
- # some error checking is required.
- if not backend.geography:
- if not isinstance(geo_field, PointField):
- raise ValueError('Spherical distance calculation only supported on PointFields.')
- if not str(Geometry(six.memoryview(params[0].ewkb)).geom_type) == 'Point':
- raise ValueError(
- 'Spherical distance calculation only supported with '
- 'Point Geometry parameters'
- )
- # The `function` procedure argument needs to be set differently for
- # geodetic distance calculations.
- if spheroid:
- # Call to distance_spheroid() requires spheroid param as well.
- procedure_fmt += ",'%(spheroid)s'"
- procedure_args.update({'function': backend.distance_spheroid, 'spheroid': params[1]})
- else:
- procedure_args.update({'function': backend.distance_sphere})
- elif length or perimeter:
- procedure_fmt = '%(geo_col)s'
- if not geography and geodetic and length:
- # There's no `length_sphere`, and `length_spheroid` also
- # works on 3D geometries.
- procedure_fmt += ",'%(spheroid)s'"
- procedure_args.update({'function': backend.length_spheroid, 'spheroid': params[1]})
- elif geom_3d and connection.features.supports_3d_functions:
- # Use 3D variants of perimeter and length routines on supported backends.
- if perimeter:
- procedure_args.update({'function': backend.perimeter3d})
- elif length:
- procedure_args.update({'function': backend.length3d})
-
- # Setting up the settings for `_spatial_attribute`.
- s = {'select_field': DistanceField(dist_att),
- 'setup': False,
- 'geo_field': geo_field,
- 'procedure_args': procedure_args,
- 'procedure_fmt': procedure_fmt,
- }
- if geom_args:
- s['geom_args'] = ('geom',)
- s['procedure_args']['geom'] = geom
- elif geom:
- # The geometry is passed in as a parameter because we handled
- # transformation conditions in this routine.
- s['select_params'] = [backend.Adapter(geom)]
- return self._spatial_attribute(func, s, **kwargs)
-
- def _geom_attribute(self, func, tolerance=0.05, **kwargs):
- """
- DRY routine for setting up a GeoQuerySet method that attaches a
- Geometry attribute (e.g., `centroid`, `point_on_surface`).
- """
- s = {'select_field': GeomField()}
- if connections[self.db].ops.oracle:
- s['procedure_fmt'] = '%(geo_col)s,%(tolerance)s'
- s['procedure_args'] = {'tolerance': tolerance}
- return self._spatial_attribute(func, s, **kwargs)
-
- def _geomset_attribute(self, func, geom, tolerance=0.05, **kwargs):
- """
- DRY routine for setting up a GeoQuerySet method that attaches a
- Geometry attribute and takes a Geoemtry parameter. This is used
- for geometry set-like operations (e.g., intersection, difference,
- union, sym_difference).
- """
- s = {
- 'geom_args': ('geom',),
- 'select_field': GeomField(),
- 'procedure_fmt': '%(geo_col)s,%(geom)s',
- 'procedure_args': {'geom': geom},
- }
- if connections[self.db].ops.oracle:
- s['procedure_fmt'] += ',%(tolerance)s'
- s['procedure_args']['tolerance'] = tolerance
- return self._spatial_attribute(func, s, **kwargs)
-
- def _geocol_select(self, geo_field, field_name):
- """
- Helper routine for constructing the SQL to select the geographic
- column. Takes into account if the geographic field is in a
- ForeignKey relation to the current model.
- """
- compiler = self.query.get_compiler(self.db)
- opts = self.model._meta
- if geo_field not in opts.fields:
- # Is this operation going to be on a related geographic field?
- # If so, it'll have to be added to the select related information
- # (e.g., if 'location__point' was given as the field name, then
- # chop the non-relational field and add select_related('location')).
- # Note: the operation really is defined as "must add select related!"
- self.query.add_select_related([field_name.rsplit(LOOKUP_SEP, 1)[0]])
- # Call pre_sql_setup() so that compiler.select gets populated.
- compiler.pre_sql_setup()
- for col, _, _ in compiler.select:
- if col.output_field == geo_field:
- return col.as_sql(compiler, compiler.connection)[0]
- raise ValueError("%r not in compiler's related_select_cols" % geo_field)
- elif geo_field not in opts.local_fields:
- # This geographic field is inherited from another model, so we have to
- # use the db table for the _parent_ model instead.
- parent_model = geo_field.model._meta.concrete_model
- return self._field_column(compiler, geo_field, parent_model._meta.db_table)
- else:
- return self._field_column(compiler, geo_field)
-
- # Private API utilities, subject to change.
- def _geo_field(self, field_name=None):
- """
- Returns the first Geometry field encountered or the one specified via
- the `field_name` keyword. The `field_name` may be a string specifying
- the geometry field on this GeoQuerySet's model, or a lookup string
- to a geometry field via a ForeignKey relation.
- """
- if field_name is None:
- # Incrementing until the first geographic field is found.
- for field in self.model._meta.fields:
- if isinstance(field, GeometryField):
- return field
- return False
- else:
- # Otherwise, check by the given field name -- which may be
- # a lookup to a _related_ geographic field.
- return GISLookup._check_geo_field(self.model._meta, field_name)
-
- def _field_column(self, compiler, field, table_alias=None, column=None):
- """
- Helper function that returns the database column for the given field.
- The table and column are returned (quoted) in the proper format, e.g.,
- `"geoapp_city"."point"`. If `table_alias` is not specified, the
- database table associated with the model of this `GeoQuerySet` will be
- used. If `column` is specified, it will be used instead of the value
- in `field.column`.
- """
- if table_alias is None:
- table_alias = compiler.query.get_meta().db_table
- return "%s.%s" % (compiler.quote_name_unless_alias(table_alias),
- compiler.connection.ops.quote_name(column or field.column))
diff --git a/docs/ref/contrib/gis/geoquerysets.txt b/docs/ref/contrib/gis/geoquerysets.txt
index 99bc4afbe4..8213e0292d 100644
--- a/docs/ref/contrib/gis/geoquerysets.txt
+++ b/docs/ref/contrib/gis/geoquerysets.txt
@@ -1,11 +1,9 @@
-=========================
-GeoQuerySet API Reference
-=========================
+==========================
+GIS QuerySet API Reference
+==========================
.. currentmodule:: django.contrib.gis.db.models
-.. class:: GeoQuerySet(model=None)
-
.. _spatial-lookups:
Spatial Lookups
@@ -720,593 +718,6 @@ SpatiaLite ``PtDistWithin(poly, geom, 5)``
SpatiaLite support was added.
-.. _geoqueryset-methods:
-
-``GeoQuerySet`` Methods
-=======================
-
-.. deprecated:: 1.9
-
- Using ``GeoQuerySet`` methods is now deprecated in favor of the new
- :doc:`functions`. Albeit a little more verbose, they are much more powerful
- in how it is possible to combine them to build more complex queries.
-
-``GeoQuerySet`` methods specify that a spatial operation be performed
-on each spatial operation on each geographic
-field in the queryset and store its output in a new attribute on the model
-(which is generally the name of the ``GeoQuerySet`` method).
-
-There are also aggregate ``GeoQuerySet`` methods which return a single value
-instead of a queryset. This section will describe the API and availability
-of every ``GeoQuerySet`` method available in GeoDjango.
-
-.. note::
-
- What methods are available depend on your spatial backend. See
- the :ref:`compatibility table <database-functions-compatibility>`
- for more details.
-
-With a few exceptions, the following keyword arguments may be used with all
-``GeoQuerySet`` methods:
-
-===================== =====================================================
-Keyword Argument Description
-===================== =====================================================
-``field_name`` By default, ``GeoQuerySet`` methods use the first
- geographic field encountered in the model. This
- keyword should be used to specify another
- geographic field (e.g., ``field_name='point2'``)
- when there are multiple geographic fields in a model.
-
- On PostGIS, the ``field_name`` keyword may also be
- used on geometry fields in models that are related
- via a ``ForeignKey`` relation (e.g.,
- ``field_name='related__point'``).
-
-``model_att`` By default, ``GeoQuerySet`` methods typically attach
- their output in an attribute with the same name as
- the ``GeoQuerySet`` method. Setting this keyword
- with the desired attribute name will override this
- default behavior. For example,
- ``qs = Zipcode.objects.centroid(model_att='c')`` will
- attach the centroid of the ``Zipcode`` geometry field
- in a ``c`` attribute on every model rather than in a
- ``centroid`` attribute.
-
- This keyword is required if
- a method name clashes with an existing
- ``GeoQuerySet`` method -- if you wanted to use the
- ``area()`` method on model with a ``PolygonField``
- named ``area``, for example.
-===================== =====================================================
-
-Measurement
------------
-*Availability*: PostGIS, Oracle, SpatiaLite
-
-``area``
-~~~~~~~~
-
-.. method:: GeoQuerySet.area(**kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.Area` function
- instead.
-
-Returns the area of the geographic field in an ``area`` attribute on
-each element of this GeoQuerySet.
-
-``distance``
-~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.distance(geom, **kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.Distance` function
- instead.
-
-This method takes a geometry as a parameter, and attaches a ``distance``
-attribute to every model in the returned queryset that contains the
-distance (as a :class:`~django.contrib.gis.measure.Distance` object) to the given geometry.
-
-In the following example (taken from the `GeoDjango distance tests`__),
-the distance from the `Tasmanian`__ city of Hobart to every other
-:class:`PointField` in the ``AustraliaCity`` queryset is calculated::
-
- >>> pnt = AustraliaCity.objects.get(name='Hobart').point
- >>> for city in AustraliaCity.objects.distance(pnt): print(city.name, city.distance)
- Wollongong 990071.220408 m
- Shellharbour 972804.613941 m
- Thirroul 1002334.36351 m
- Mittagong 975691.632637 m
- Batemans Bay 834342.185561 m
- Canberra 598140.268959 m
- Melbourne 575337.765042 m
- Sydney 1056978.87363 m
- Hobart 0.0 m
- Adelaide 1162031.83522 m
- Hillsdale 1049200.46122 m
-
-.. note::
-
- Because the ``distance`` attribute is a
- :class:`~django.contrib.gis.measure.Distance` object, you can easily express
- the value in the units of your choice. For example, ``city.distance.mi`` is
- the distance value in miles and ``city.distance.km`` is the distance value
- in kilometers. See :doc:`measure` for usage details and the list of
- :ref:`supported_units`.
-
-__ https://github.com/django/django/blob/master/tests/gis_tests/distapp/models.py
-__ https://en.wikipedia.org/wiki/Tasmania
-
-``length``
-~~~~~~~~~~
-
-.. method:: GeoQuerySet.length(**kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.Length` function
- instead.
-
-Returns the length of the geometry field in a ``length`` attribute
-(a :class:`~django.contrib.gis.measure.Distance` object) on each model in
-the queryset.
-
-``perimeter``
-~~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.perimeter(**kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.Perimeter` function
- instead.
-
-Returns the perimeter of the geometry field in a ``perimeter`` attribute
-(a :class:`~django.contrib.gis.measure.Distance` object) on each model in
-the queryset.
-
-Geometry Relationships
-----------------------
-
-The following methods take no arguments, and attach geometry objects
-each element of the :class:`GeoQuerySet` that is the result of relationship
-function evaluated on the geometry field.
-
-``centroid``
-~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.centroid(**kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.Centroid` function
- instead.
-
-*Availability*: PostGIS, Oracle, SpatiaLite
-
-Returns the ``centroid`` value for the geographic field in a ``centroid``
-attribute on each element of the ``GeoQuerySet``.
-
-``envelope``
-~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.envelope(**kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.Envelope` function
- instead.
-
-*Availability*: PostGIS, SpatiaLite
-
-Returns a geometry representing the bounding box of the geometry field in
-an ``envelope`` attribute on each element of the ``GeoQuerySet``.
-
-``point_on_surface``
-~~~~~~~~~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.point_on_surface(**kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.PointOnSurface`
- function instead.
-
-*Availability*: PostGIS, Oracle, SpatiaLite
-
-Returns a Point geometry guaranteed to lie on the surface of the
-geometry field in a ``point_on_surface`` attribute on each element
-of the queryset; otherwise sets with None.
-
-Geometry Editors
-----------------
-
-``force_rhr``
-~~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.force_rhr(**kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.ForceRHR` function
- instead.
-
-*Availability*: PostGIS
-
-Returns a modified version of the polygon/multipolygon in which all
-of the vertices follow the Right-Hand-Rule, and attaches as a
-``force_rhr`` attribute on each element of the queryset.
-
-``reverse_geom``
-~~~~~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.reverse_geom(**kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.Reverse` function
- instead.
-
-*Availability*: PostGIS, Oracle
-
-Reverse the coordinate order of the geometry field, and attaches as a
-``reverse`` attribute on each element of the queryset.
-
-``scale``
-~~~~~~~~~
-
-.. method:: GeoQuerySet.scale(x, y, z=0.0, **kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.Scale` function
- instead.
-
-*Availability*: PostGIS, SpatiaLite
-
-``snap_to_grid``
-~~~~~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.snap_to_grid(*args, **kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.SnapToGrid` function
- instead.
-
-Snap all points of the input geometry to the grid. How the
-geometry is snapped to the grid depends on how many numeric
-(either float, integer, or long) arguments are given.
-
-=================== =====================================================
-Number of Arguments Description
-=================== =====================================================
-1 A single size to snap bot the X and Y grids to.
-2 X and Y sizes to snap the grid to.
-4 X, Y sizes and the corresponding X, Y origins.
-=================== =====================================================
-
-``transform``
-~~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.transform(srid=4326, **kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.Transform` function
- instead.
-
-*Availability*: PostGIS, Oracle, SpatiaLite
-
-The ``transform`` method transforms the geometry field of a model to the spatial
-reference system specified by the ``srid`` parameter. If no ``srid`` is given,
-then 4326 (WGS84) is used by default.
-
-.. note::
-
- Unlike other ``GeoQuerySet`` methods, ``transform`` stores its output
- "in-place". In other words, no new attribute for the transformed
- geometry is placed on the models.
-
-.. note::
-
- What spatial reference system an integer SRID corresponds to may depend on
- the spatial database used. In other words, the SRID numbers used for Oracle
- are not necessarily the same as those used by PostGIS.
-
-Example::
-
- >>> qs = Zipcode.objects.all().transform() # Transforms to WGS84
- >>> qs = Zipcode.objects.all().transform(32140) # Transforming to "NAD83 / Texas South Central"
- >>> print(qs[0].poly.srid)
- 32140
- >>> print(qs[0].poly)
- POLYGON ((234055.1698884720099159 4937796.9232223574072123 ...
-
-``translate``
-~~~~~~~~~~~~~
-.. method:: GeoQuerySet.translate(x, y, z=0.0, **kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.Translate` function
- instead.
-
-*Availability*: PostGIS, SpatiaLite
-
-Translates the geometry field to a new location using the given numeric
-parameters as offsets.
-
-Geometry Operations
--------------------
-*Availability*: PostGIS, Oracle, SpatiaLite
-
-The following methods all take a geometry as a parameter and attach a geometry
-to each element of the ``GeoQuerySet`` that is the result of the operation.
-
-``difference``
-~~~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.difference(geom)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.Difference` function
- instead.
-
-Returns the spatial difference of the geographic field with the given
-geometry in a ``difference`` attribute on each element of the
-``GeoQuerySet``.
-
-
-``intersection``
-~~~~~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.intersection(geom)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.Intersection`
- function instead.
-
-Returns the spatial intersection of the geographic field with the
-given geometry in an ``intersection`` attribute on each element of the
-``GeoQuerySet``.
-
-``sym_difference``
-~~~~~~~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.sym_difference(geom)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.SymDifference`
- function instead.
-
-Returns the symmetric difference of the geographic field with the
-given geometry in a ``sym_difference`` attribute on each element of the
-``GeoQuerySet``.
-
-``union``
-~~~~~~~~~
-
-.. method:: GeoQuerySet.union(geom)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.Union` function
- instead.
-
-Returns the union of the geographic field with the given
-geometry in an ``union`` attribute on each element of the
-``GeoQuerySet``.
-
-Geometry Output
----------------
-
-The following ``GeoQuerySet`` methods will return an attribute that has the value
-of the geometry field in each model converted to the requested output format.
-
-``geohash``
-~~~~~~~~~~~
-
-.. method:: GeoQuerySet.geohash(precision=20, **kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.GeoHash` function
- instead.
-
-Attaches a ``geohash`` attribute to every model the queryset
-containing the `GeoHash`__ representation of the geometry.
-
-__ http://geohash.org/
-
-``geojson``
-~~~~~~~~~~~
-
-.. method:: GeoQuerySet.geojson(**kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.AsGeoJSON` function
- instead.
-
-*Availability*: PostGIS, SpatiaLite
-
-Attaches a ``geojson`` attribute to every model in the queryset that contains the
-`GeoJSON`__ representation of the geometry.
-
-===================== =====================================================
-Keyword Argument Description
-===================== =====================================================
-``precision`` It may be used to specify the number of significant
- digits for the coordinates in the GeoJSON
- representation -- the default value is 8.
-
-``crs`` Set this to ``True`` if you want the coordinate
- reference system to be included in the returned
- GeoJSON.
-
-``bbox`` Set this to ``True`` if you want the bounding box
- to be included in the returned GeoJSON.
-===================== =====================================================
-
-__ http://geojson.org/
-
-``gml``
-~~~~~~~
-
-.. method:: GeoQuerySet.gml(**kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.AsGML` function
- instead.
-
-*Availability*: PostGIS, Oracle, SpatiaLite
-
-Attaches a ``gml`` attribute to every model in the queryset that contains the
-`Geographic Markup Language (GML)`__ representation of the geometry.
-
-Example::
-
- >>> qs = Zipcode.objects.all().gml()
- >>> print(qs[0].gml)
- <gml:Polygon srsName="EPSG:4326"><gml:OuterBoundaryIs>-147.78711,70.245363 ... -147.78711,70.245363</gml:OuterBoundaryIs></gml:Polygon>
-
-===================== =====================================================
-Keyword Argument Description
-===================== =====================================================
-``precision`` This keyword is for PostGIS only. It may be used
- to specify the number of significant digits for the
- coordinates in the GML representation -- the default
- value is 8.
-
-``version`` This keyword is for PostGIS only. It may be used to
- specify the GML version used, and may only be values
- of 2 or 3. The default value is 2.
-===================== =====================================================
-
-__ https://en.wikipedia.org/wiki/Geography_Markup_Language
-
-``kml``
-~~~~~~~
-
-.. method:: GeoQuerySet.kml(**kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.AsKML` function
- instead.
-
-*Availability*: PostGIS, SpatiaLite
-
-Attaches a ``kml`` attribute to every model in the queryset that contains the
-`Keyhole Markup Language (KML)`__ representation of the geometry fields. It
-should be noted that the contents of the KML are transformed to WGS84 if
-necessary.
-
-Example::
-
- >>> qs = Zipcode.objects.all().kml()
- >>> print(qs[0].kml)
- <Polygon><outerBoundaryIs><LinearRing><coordinates>-103.04135,36.217596,0 ... -103.04135,36.217596,0</coordinates></LinearRing></outerBoundaryIs></Polygon>
-
-===================== =====================================================
-Keyword Argument Description
-===================== =====================================================
-``precision`` This keyword may be used to specify the number of
- significant digits for the coordinates in the KML
- representation -- the default value is 8.
-===================== =====================================================
-
-__ https://developers.google.com/kml/documentation/
-
-``svg``
-~~~~~~~
-
-.. method:: GeoQuerySet.svg(**kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.AsSVG` function
- instead.
-
-*Availability*: PostGIS, SpatiaLite
-
-Attaches a ``svg`` attribute to every model in the queryset that contains
-the `Scalable Vector Graphics (SVG)`__ path data of the geometry fields.
-
-===================== =====================================================
-Keyword Argument Description
-===================== =====================================================
-``relative`` If set to ``True``, the path data will be implemented
- in terms of relative moves. Defaults to ``False``,
- meaning that absolute moves are used instead.
-
-``precision`` This keyword may be used to specify the number of
- significant digits for the coordinates in the SVG
- representation -- the default value is 8.
-===================== =====================================================
-
-__ http://www.w3.org/Graphics/SVG/
-
-Miscellaneous
--------------
-
-``mem_size``
-~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.mem_size(**kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.MemSize` function
- instead.
-
-*Availability*: PostGIS
-
-Returns the memory size (number of bytes) that the geometry field takes
-in a ``mem_size`` attribute on each element of the ``GeoQuerySet``.
-
-``num_geom``
-~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.num_geom(**kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.NumGeometries`
- function instead.
-
-*Availability*: PostGIS, Oracle, SpatiaLite
-
-Returns the number of geometries in a ``num_geom`` attribute on
-each element of the ``GeoQuerySet`` if the geometry field is a
-collection (e.g., a ``GEOMETRYCOLLECTION`` or ``MULTI*`` field);
-otherwise sets with ``None``.
-
-``num_points``
-~~~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.num_points(**kwargs)
-
-.. deprecated:: 1.9
-
- Use the :class:`~django.contrib.gis.db.models.functions.NumPoints` function
- instead.
-
-*Availability*: PostGIS, Oracle, SpatiaLite
-
-Returns the number of points in the first linestring in the
-geometry field in a ``num_points`` attribute on each element of
-the ``GeoQuerySet``; otherwise sets with ``None``.
-
Aggregate Functions
-------------------
diff --git a/docs/ref/contrib/gis/model-api.txt b/docs/ref/contrib/gis/model-api.txt
index 732b3f8f6f..54a6df4dc4 100644
--- a/docs/ref/contrib/gis/model-api.txt
+++ b/docs/ref/contrib/gis/model-api.txt
@@ -244,22 +244,6 @@ For more information, the PostGIS documentation contains a helpful section on
determining `when to use geography data type over geometry data type
<http://postgis.net/docs/using_postgis_dbmanagement.html#PostGIS_GeographyVSGeometry>`_.
-``GeoManager``
-==============
-
-.. currentmodule:: django.contrib.gis.db.models
-.. class:: GeoManager
-
-The ``GeoManager`` is required in order to use the legacy
-:ref:`geoqueryset-methods`.
-
-.. deprecated:: 1.9
-
- All ``GeoQuerySet`` methods have been deprecated and replaced by
- :doc:`equivalent database functions </ref/contrib/gis/functions>`. As soon
- as the legacy methods have been replaced in your code, you should be able
- to remove the special ``GeoManager`` from your GIS-enabled classes.
-
.. rubric:: Footnotes
.. [#fnogc] OpenGIS Consortium, Inc., `Simple Feature Specification For SQL <http://www.opengeospatial.org/standards/sfs>`_.
.. [#fnogcsrid] *See id.* at Ch. 2.3.8, p. 39 (Geometry Values and Spatial Reference Systems).
diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
index f5f0fbcc8b..ee48a3c6f0 100644
--- a/docs/ref/models/querysets.txt
+++ b/docs/ref/models/querysets.txt
@@ -149,11 +149,10 @@ Here's the formal declaration of a ``QuerySet``:
.. note::
The ``query`` parameter to :class:`QuerySet` exists so that specialized
- query subclasses such as
- :class:`~django.contrib.gis.db.models.GeoQuerySet` can reconstruct
- internal query state. The value of the parameter is an opaque
- representation of that query state and is not part of a public API.
- To put it simply: if you need to ask, you don't need to use it.
+ query subclasses can reconstruct internal query state. The value of the
+ parameter is an opaque representation of that query state and is not
+ part of a public API. To put it simply: if you need to ask, you don't
+ need to use it.
.. currentmodule:: django.db.models.query.QuerySet
diff --git a/docs/releases/1.2.txt b/docs/releases/1.2.txt
index c2676a90cc..3995ee7192 100644
--- a/docs/releases/1.2.txt
+++ b/docs/releases/1.2.txt
@@ -359,12 +359,8 @@ keyword to 3 in your :class:`~django.contrib.gis.db.models.GeometryField`.
The :class:`~django.contrib.gis.db.models.Extent3D` aggregate
and ``extent3d()`` ``GeoQuerySet`` method were added as a part of this feature.
-The following :class:`~django.contrib.gis.db.models.GeoQuerySet`
-methods are new in 1.2:
-
-* :meth:`~django.contrib.gis.db.models.GeoQuerySet.force_rhr`
-* :meth:`~django.contrib.gis.db.models.GeoQuerySet.reverse_geom`
-* :meth:`~django.contrib.gis.db.models.GeoQuerySet.geohash`
+The ``force_rhr()``, ``reverse_geom()``, and ``geohash()`` ``GeoQuerySet``
+methods are new.
The GEOS interface was updated to use thread-safe C library functions when
available on the platform.
diff --git a/docs/releases/2.0.txt b/docs/releases/2.0.txt
index c87faba783..88b24e9b55 100644
--- a/docs/releases/2.0.txt
+++ b/docs/releases/2.0.txt
@@ -261,3 +261,5 @@ these features.
ORM, e.g. with ``cursor.execute()``.
* ``django.contrib.auth.tests.utils.skipIfCustomUser()`` is removed.
+
+* The ``GeoManager`` and ``GeoQuerySet`` classes are removed.
diff --git a/tests/gis_tests/distapp/models.py b/tests/gis_tests/distapp/models.py
index be4cf50f95..43a2acacdf 100644
--- a/tests/gis_tests/distapp/models.py
+++ b/tests/gis_tests/distapp/models.py
@@ -8,8 +8,6 @@ from ..utils import gisfield_may_be_null
class NamedModel(models.Model):
name = models.CharField(max_length=30)
- objects = models.GeoManager()
-
class Meta:
abstract = True
required_db_features = ['gis_enabled']
diff --git a/tests/gis_tests/distapp/tests.py b/tests/gis_tests/distapp/tests.py
index 3079afb9d7..01f0a620dc 100644
--- a/tests/gis_tests/distapp/tests.py
+++ b/tests/gis_tests/distapp/tests.py
@@ -1,7 +1,5 @@
from __future__ import unicode_literals
-from unittest import skipIf
-
from django.contrib.gis.db.models.functions import (
Area, Distance, Length, Perimeter, Transform,
)
@@ -9,8 +7,7 @@ from django.contrib.gis.geos import GEOSGeometry, LineString, Point
from django.contrib.gis.measure import D # alias for Distance
from django.db import connection
from django.db.models import F, Q
-from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
-from django.utils.deprecation import RemovedInDjango20Warning
+from django.test import TestCase, skipUnlessDBFeature
from ..utils import no_oracle, oracle, postgis, spatialite
from .models import (
@@ -101,136 +98,6 @@ class DistanceTest(TestCase):
else:
self.assertListEqual(au_cities, self.get_names(qs.filter(point__dwithin=(self.au_pnt, dist))))
- @skipUnlessDBFeature("has_distance_method")
- @ignore_warnings(category=RemovedInDjango20Warning)
- def test_distance_projected(self):
- """
- Test the `distance` GeoQuerySet method on projected coordinate systems.
- """
- # The point for La Grange, TX
- lagrange = GEOSGeometry('POINT(-96.876369 29.905320)', 4326)
- # Reference distances in feet and in meters. Got these values from
- # using the provided raw SQL statements.
- # SELECT ST_Distance(point, ST_Transform(ST_GeomFromText('POINT(-96.876369 29.905320)', 4326), 32140))
- # FROM distapp_southtexascity;
- m_distances = [147075.069813, 139630.198056, 140888.552826,
- 138809.684197, 158309.246259, 212183.594374,
- 70870.188967, 165337.758878, 139196.085105]
- # SELECT ST_Distance(point, ST_Transform(ST_GeomFromText('POINT(-96.876369 29.905320)', 4326), 2278))
- # FROM distapp_southtexascityft;
- # Oracle 11 thinks this is not a projected coordinate system, so it's
- # not tested.
- ft_distances = [482528.79154625, 458103.408123001, 462231.860397575,
- 455411.438904354, 519386.252102563, 696139.009211594,
- 232513.278304279, 542445.630586414, 456679.155883207]
-
- # Testing using different variations of parameters and using models
- # with different projected coordinate systems.
- dist1 = SouthTexasCity.objects.distance(lagrange, field_name='point').order_by('id')
- dist2 = SouthTexasCity.objects.distance(lagrange).order_by('id') # Using GEOSGeometry parameter
- if oracle:
- dist_qs = [dist1, dist2]
- else:
- dist3 = SouthTexasCityFt.objects.distance(lagrange.ewkt).order_by('id') # Using EWKT string parameter.
- dist4 = SouthTexasCityFt.objects.distance(lagrange).order_by('id')
- dist_qs = [dist1, dist2, dist3, dist4]
-
- # Original query done on PostGIS, have to adjust AlmostEqual tolerance
- # for Oracle.
- tol = 2 if oracle else 5
-
- # Ensuring expected distances are returned for each distance queryset.
- for qs in dist_qs:
- for i, c in enumerate(qs):
- self.assertAlmostEqual(m_distances[i], c.distance.m, tol)
- self.assertAlmostEqual(ft_distances[i], c.distance.survey_ft, tol)
-
- @skipIf(spatialite, "distance method doesn't support geodetic coordinates on SpatiaLite.")
- @skipUnlessDBFeature("has_distance_method", "supports_distance_geodetic")
- @ignore_warnings(category=RemovedInDjango20Warning)
- def test_distance_geodetic(self):
- """
- Test the `distance` GeoQuerySet method on geodetic coordinate systems.
- """
- tol = 2 if oracle else 4
-
- # Testing geodetic distance calculation with a non-point geometry
- # (a LineString of Wollongong and Shellharbour coords).
- ls = LineString(((150.902, -34.4245), (150.87, -34.5789)))
-
- # Reference query:
- # SELECT ST_distance_sphere(point, ST_GeomFromText('LINESTRING(150.9020 -34.4245,150.8700 -34.5789)', 4326))
- # FROM distapp_australiacity ORDER BY name;
- distances = [1120954.92533513, 140575.720018241, 640396.662906304,
- 60580.9693849269, 972807.955955075, 568451.8357838,
- 40435.4335201384, 0, 68272.3896586844, 12375.0643697706, 0]
- qs = AustraliaCity.objects.distance(ls).order_by('name')
- for city, distance in zip(qs, distances):
- # Testing equivalence to within a meter.
- self.assertAlmostEqual(distance, city.distance.m, 0)
-
- # Got the reference distances using the raw SQL statements:
- # SELECT ST_distance_spheroid(point, ST_GeomFromText('POINT(151.231341 -33.952685)', 4326),
- # 'SPHEROID["WGS 84",6378137.0,298.257223563]') FROM distapp_australiacity WHERE (NOT (id = 11));
- # SELECT ST_distance_sphere(point, ST_GeomFromText('POINT(151.231341 -33.952685)', 4326))
- # FROM distapp_australiacity WHERE (NOT (id = 11)); st_distance_sphere
- spheroid_distances = [
- 60504.0628957201, 77023.9489850262, 49154.8867574404,
- 90847.4358768573, 217402.811919332, 709599.234564757,
- 640011.483550888, 7772.00667991925, 1047861.78619339,
- 1165126.55236034,
- ]
- sphere_distances = [
- 60580.9693849267, 77144.0435286473, 49199.4415344719,
- 90804.7533823494, 217713.384600405, 709134.127242793,
- 639828.157159169, 7786.82949717788, 1049204.06569028,
- 1162623.7238134,
- ]
- # Testing with spheroid distances first.
- hillsdale = AustraliaCity.objects.get(name='Hillsdale')
- qs = AustraliaCity.objects.exclude(id=hillsdale.id).distance(hillsdale.point, spheroid=True).order_by('id')
- for i, c in enumerate(qs):
- self.assertAlmostEqual(spheroid_distances[i], c.distance.m, tol)
- if postgis:
- # PostGIS uses sphere-only distances by default, testing these as well.
- qs = AustraliaCity.objects.exclude(id=hillsdale.id).distance(hillsdale.point).order_by('id')
- for i, c in enumerate(qs):
- self.assertAlmostEqual(sphere_distances[i], c.distance.m, tol)
-
- @no_oracle # Oracle already handles geographic distance calculation.
- @skipUnlessDBFeature("has_distance_method")
- @ignore_warnings(category=RemovedInDjango20Warning)
- def test_distance_transform(self):
- """
- Test the `distance` GeoQuerySet method used with `transform` on a geographic field.
- """
- # We'll be using a Polygon (created by buffering the centroid
- # of 77005 to 100m) -- which aren't allowed in geographic distance
- # queries normally, however our field has been transformed to
- # a non-geographic system.
- z = SouthTexasZipcode.objects.get(name='77005')
-
- # Reference query:
- # SELECT ST_Distance(ST_Transform("distapp_censuszipcode"."poly", 32140),
- # ST_GeomFromText('<buffer_wkt>', 32140))
- # FROM "distapp_censuszipcode";
- dists_m = [3553.30384972258, 1243.18391525602, 2186.15439472242]
-
- # Having our buffer in the SRID of the transformation and of the field
- # -- should get the same results. The first buffer has no need for
- # transformation SQL because it is the same SRID as what was given
- # to `transform()`. The second buffer will need to be transformed,
- # however.
- buf1 = z.poly.centroid.buffer(100)
- buf2 = buf1.transform(4269, clone=True)
- ref_zips = ['77002', '77025', '77401']
-
- for buf in [buf1, buf2]:
- qs = CensusZipcode.objects.exclude(name='77005').transform(32140).distance(buf).order_by('name')
- self.assertListEqual(ref_zips, self.get_names(qs))
- for i, z in enumerate(qs):
- self.assertAlmostEqual(z.distance.m, dists_m[i], 5)
-
@skipUnlessDBFeature("supports_distances_lookups")
def test_distance_lookups(self):
"""
@@ -347,86 +214,6 @@ class DistanceTest(TestCase):
).order_by('name')
self.assertEqual(self.get_names(qs), ['Canberra', 'Hobart', 'Melbourne'])
- @skipUnlessDBFeature("has_area_method")
- @ignore_warnings(category=RemovedInDjango20Warning)
- def test_area(self):
- """
- Test the `area` GeoQuerySet method.
- """
- # Reference queries:
- # SELECT ST_Area(poly) FROM distapp_southtexaszipcode;
- area_sq_m = [5437908.90234375, 10183031.4389648, 11254471.0073242, 9881708.91772461]
- # Tolerance has to be lower for Oracle
- tol = 2
- for i, z in enumerate(SouthTexasZipcode.objects.order_by('name').area()):
- self.assertAlmostEqual(area_sq_m[i], z.area.sq_m, tol)
-
- @skipIf(spatialite, "length method doesn't support geodetic coordinates on SpatiaLite.")
- @skipUnlessDBFeature("has_length_method")
- @ignore_warnings(category=RemovedInDjango20Warning)
- def test_length(self):
- """
- Test the `length` GeoQuerySet method.
- """
- # Reference query (should use `length_spheroid`).
- # SELECT ST_length_spheroid(ST_GeomFromText('<wkt>', 4326) 'SPHEROID["WGS 84",6378137,298.257223563,
- # AUTHORITY["EPSG","7030"]]');
- len_m1 = 473504.769553813
- len_m2 = 4617.668
-
- if connection.features.supports_distance_geodetic:
- qs = Interstate.objects.length()
- tol = 2 if oracle else 3
- self.assertAlmostEqual(len_m1, qs[0].length.m, tol)
- else:
- # Does not support geodetic coordinate systems.
- with self.assertRaises(ValueError):
- Interstate.objects.length()
-
- # Now doing length on a projected coordinate system.
- i10 = SouthTexasInterstate.objects.length().get(name='I-10')
- self.assertAlmostEqual(len_m2, i10.length.m, 2)
-
- @skipUnlessDBFeature("has_perimeter_method")
- @ignore_warnings(category=RemovedInDjango20Warning)
- def test_perimeter(self):
- """
- Test the `perimeter` GeoQuerySet method.
- """
- # Reference query:
- # SELECT ST_Perimeter(distapp_southtexaszipcode.poly) FROM distapp_southtexaszipcode;
- perim_m = [18404.3550889361, 15627.2108551001, 20632.5588368978, 17094.5996143697]
- tol = 2 if oracle else 7
- for i, z in enumerate(SouthTexasZipcode.objects.order_by('name').perimeter()):
- self.assertAlmostEqual(perim_m[i], z.perimeter.m, tol)
-
- # Running on points; should return 0.
- for i, c in enumerate(SouthTexasCity.objects.perimeter(model_att='perim')):
- self.assertEqual(0, c.perim.m)
-
- @skipUnlessDBFeature("has_area_method", "has_distance_method")
- @ignore_warnings(category=RemovedInDjango20Warning)
- def test_measurement_null_fields(self):
- """
- Test the measurement GeoQuerySet methods on fields with NULL values.
- """
- # Creating SouthTexasZipcode w/NULL value.
- SouthTexasZipcode.objects.create(name='78212')
- # Performing distance/area queries against the NULL PolygonField,
- # and ensuring the result of the operations is None.
- htown = SouthTexasCity.objects.get(name='Downtown Houston')
- z = SouthTexasZipcode.objects.distance(htown.point).area().get(name='78212')
- self.assertIsNone(z.distance)
- self.assertIsNone(z.area)
-
- @skipUnlessDBFeature("has_distance_method")
- @ignore_warnings(category=RemovedInDjango20Warning)
- def test_distance_order_by(self):
- qs = SouthTexasCity.objects.distance(Point(3, 3)).order_by(
- 'distance'
- ).values_list('name', flat=True).filter(name__in=('San Antonio', 'Pearland'))
- self.assertSequenceEqual(qs, ['San Antonio', 'Pearland'])
-
'''
=============================
diff --git a/tests/gis_tests/geo3d/models.py b/tests/gis_tests/geo3d/models.py
index f2ea0e02d9..42467c5ce4 100644
--- a/tests/gis_tests/geo3d/models.py
+++ b/tests/gis_tests/geo3d/models.py
@@ -6,8 +6,6 @@ from django.utils.encoding import python_2_unicode_compatible
class NamedModel(models.Model):
name = models.CharField(max_length=30)
- objects = models.GeoManager()
-
class Meta:
abstract = True
required_db_features = ['gis_enabled']
diff --git a/tests/gis_tests/geo3d/tests.py b/tests/gis_tests/geo3d/tests.py
index f180387aac..946928b919 100644
--- a/tests/gis_tests/geo3d/tests.py
+++ b/tests/gis_tests/geo3d/tests.py
@@ -8,9 +8,8 @@ from django.contrib.gis.db.models.functions import (
AsGeoJSON, AsKML, Length, Perimeter, Scale, Translate,
)
from django.contrib.gis.geos import GEOSGeometry, LineString, Point, Polygon
-from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
+from django.test import TestCase, skipUnlessDBFeature
from django.utils._os import upath
-from django.utils.deprecation import RemovedInDjango20Warning
from .models import (
City3D, Interstate2D, Interstate3D, InterstateProj2D, InterstateProj3D,
@@ -171,30 +170,6 @@ class Geo3DTest(Geo3DLoadingHelper, TestCase):
lm.save()
self.assertEqual(3, MultiPoint3D.objects.count())
- @ignore_warnings(category=RemovedInDjango20Warning)
- def test_kml(self):
- """
- Test GeoQuerySet.kml() with Z values.
- """
- self._load_city_data()
- h = City3D.objects.kml(precision=6).get(name='Houston')
- # KML should be 3D.
- # `SELECT ST_AsKML(point, 6) FROM geo3d_city3d WHERE name = 'Houston';`
- ref_kml_regex = re.compile(r'^<Point><coordinates>-95.363\d+,29.763\d+,18</coordinates></Point>$')
- self.assertTrue(ref_kml_regex.match(h.kml))
-
- @ignore_warnings(category=RemovedInDjango20Warning)
- def test_geojson(self):
- """
- Test GeoQuerySet.geojson() with Z values.
- """
- self._load_city_data()
- h = City3D.objects.geojson(precision=6).get(name='Houston')
- # GeoJSON should be 3D
- # `SELECT ST_AsGeoJSON(point, 6) FROM geo3d_city3d WHERE name='Houston';`
- ref_json_regex = re.compile(r'^{"type":"Point","coordinates":\[-95.363151,29.763374,18(\.0+)?\]}$')
- self.assertTrue(ref_json_regex.match(h.geojson))
-
@skipUnlessDBFeature("supports_3d_functions")
def test_union(self):
"""
@@ -231,84 +206,6 @@ class Geo3DTest(Geo3DLoadingHelper, TestCase):
check_extent3d(extent)
self.assertIsNone(City3D.objects.none().aggregate(Extent3D('point'))['point__extent3d'])
- @ignore_warnings(category=RemovedInDjango20Warning)
- @skipUnlessDBFeature("supports_3d_functions")
- def test_perimeter(self):
- """
- Testing GeoQuerySet.perimeter() on 3D fields.
- """
- self._load_polygon_data()
- # Reference query for values below:
- # `SELECT ST_Perimeter3D(poly), ST_Perimeter2D(poly) FROM geo3d_polygon3d;`
- ref_perim_3d = 76859.2620451
- ref_perim_2d = 76859.2577803
- tol = 6
- self.assertAlmostEqual(ref_perim_2d,
- Polygon2D.objects.perimeter().get(name='2D BBox').perimeter.m,
- tol)
- self.assertAlmostEqual(ref_perim_3d,
- Polygon3D.objects.perimeter().get(name='3D BBox').perimeter.m,
- tol)
-
- @ignore_warnings(category=RemovedInDjango20Warning)
- @skipUnlessDBFeature("supports_3d_functions")
- def test_length(self):
- """
- Testing GeoQuerySet.length() on 3D fields.
- """
- # ST_Length_Spheroid Z-aware, and thus does not need to use
- # a separate function internally.
- # `SELECT ST_Length_Spheroid(line, 'SPHEROID["GRS 1980",6378137,298.257222101]')
- # FROM geo3d_interstate[2d|3d];`
- self._load_interstate_data()
- tol = 3
- ref_length_2d = 4368.1721949481
- ref_length_3d = 4368.62547052088
- self.assertAlmostEqual(ref_length_2d,
- Interstate2D.objects.length().get(name='I-45').length.m,
- tol)
- self.assertAlmostEqual(ref_length_3d,
- Interstate3D.objects.length().get(name='I-45').length.m,
- tol)
-
- # Making sure `ST_Length3D` is used on for a projected
- # and 3D model rather than `ST_Length`.
- # `SELECT ST_Length(line) FROM geo3d_interstateproj2d;`
- ref_length_2d = 4367.71564892392
- # `SELECT ST_Length3D(line) FROM geo3d_interstateproj3d;`
- ref_length_3d = 4368.16897234101
- self.assertAlmostEqual(ref_length_2d,
- InterstateProj2D.objects.length().get(name='I-45').length.m,
- tol)
- self.assertAlmostEqual(ref_length_3d,
- InterstateProj3D.objects.length().get(name='I-45').length.m,
- tol)
-
- @ignore_warnings(category=RemovedInDjango20Warning)
- @skipUnlessDBFeature("supports_3d_functions")
- def test_scale(self):
- """
- Testing GeoQuerySet.scale() on Z values.
- """
- self._load_city_data()
- # Mapping of City name to reference Z values.
- zscales = (-3, 4, 23)
- for zscale in zscales:
- for city in City3D.objects.scale(1.0, 1.0, zscale):
- self.assertEqual(city_dict[city.name][2] * zscale, city.scale.z)
-
- @ignore_warnings(category=RemovedInDjango20Warning)
- @skipUnlessDBFeature("supports_3d_functions")
- def test_translate(self):
- """
- Testing GeoQuerySet.translate() on Z values.
- """
- self._load_city_data()
- ztranslations = (5.23, 23, -17)
- for ztrans in ztranslations:
- for city in City3D.objects.translate(0, 0, ztrans):
- self.assertEqual(city_dict[city.name][2] + ztrans, city.translate.z)
-
@skipUnlessDBFeature("gis_enabled", "supports_3d_functions")
class Geo3DFunctionsTests(Geo3DLoadingHelper, TestCase):
diff --git a/tests/gis_tests/geoapp/models.py b/tests/gis_tests/geoapp/models.py
index 62103d268d..f5f4c38b42 100644
--- a/tests/gis_tests/geoapp/models.py
+++ b/tests/gis_tests/geoapp/models.py
@@ -8,8 +8,6 @@ from ..utils import gisfield_may_be_null
class NamedModel(models.Model):
name = models.CharField(max_length=30)
- objects = models.GeoManager()
-
class Meta:
abstract = True
required_db_features = ['gis_enabled']
diff --git a/tests/gis_tests/geoapp/test_functions.py b/tests/gis_tests/geoapp/test_functions.py
index 61ae7dc9a6..e551de6890 100644
--- a/tests/gis_tests/geoapp/test_functions.py
+++ b/tests/gis_tests/geoapp/test_functions.py
@@ -19,7 +19,6 @@ from .models import City, Country, CountryWebMercator, State, Track
class GISFunctionsTests(TestCase):
"""
Testing functions from django/contrib/gis/db/models/functions.py.
- Several tests are taken and adapted from GeoQuerySetTest.
Area/Distance/Length/Perimeter are tested in distapp/tests.
Please keep the tests in function's alphabetic order.
@@ -462,7 +461,6 @@ class GISFunctionsTests(TestCase):
"has_Difference_function", "has_Intersection_function",
"has_SymDifference_function", "has_Union_function")
def test_diff_intersection_union(self):
- "Testing the `difference`, `intersection`, `sym_difference`, and `union` GeoQuerySet methods."
geom = Point(5, 23, srid=4326)
qs = Country.objects.all().annotate(
difference=functions.Difference('mpoly', geom),
diff --git a/tests/gis_tests/geoapp/test_regress.py b/tests/gis_tests/geoapp/test_regress.py
index 7aa99966e3..a075d447ef 100644
--- a/tests/gis_tests/geoapp/test_regress.py
+++ b/tests/gis_tests/geoapp/test_regress.py
@@ -17,7 +17,7 @@ class GeoRegressionTests(TestCase):
fixtures = ['initial']
def test_update(self):
- "Testing GeoQuerySet.update(). See #10411."
+ "Testing QuerySet.update() (#10411)."
pnt = City.objects.get(name='Pueblo').point
bak = pnt.clone()
pnt.y += 0.005
diff --git a/tests/gis_tests/geoapp/tests.py b/tests/gis_tests/geoapp/tests.py
index 7c4e8b8dfb..cbbf0357bc 100644
--- a/tests/gis_tests/geoapp/tests.py
+++ b/tests/gis_tests/geoapp/tests.py
@@ -1,21 +1,19 @@
from __future__ import unicode_literals
-import re
import tempfile
from django.contrib.gis import gdal
-from django.contrib.gis.db.models import Extent, MakeLine, Union
+from django.contrib.gis.db.models import Extent, MakeLine, Union, functions
from django.contrib.gis.geos import (
GeometryCollection, GEOSGeometry, LinearRing, LineString, MultiLineString,
MultiPoint, MultiPolygon, Point, Polygon, fromstr,
)
from django.core.management import call_command
from django.db import connection
-from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
+from django.test import TestCase, skipUnlessDBFeature
from django.utils import six
-from django.utils.deprecation import RemovedInDjango20Warning
-from ..utils import oracle, postgis, skipUnlessGISLookup, spatialite
+from ..utils import no_oracle, oracle, postgis, skipUnlessGISLookup, spatialite
from .models import (
City, Country, Feature, MinusOneSRID, NonConcreteModel, PennsylvaniaCity,
State, Track,
@@ -155,19 +153,22 @@ class GeoModelTest(TestCase):
self.assertIsInstance(f_4.geom, GeometryCollection)
self.assertEqual(f_3.geom, f_4.geom[2])
+ # TODO: fix on Oracle: ORA-22901: cannot compare nested table or VARRAY or
+ # LOB attributes of an object type.
+ @no_oracle
@skipUnlessDBFeature("supports_transform")
def test_inherited_geofields(self):
- "Test GeoQuerySet methods on inherited Geometry fields."
+ "Database functions on inherited Geometry fields."
# Creating a Pennsylvanian city.
PennsylvaniaCity.objects.create(name='Mansfield', county='Tioga', point='POINT(-77.071445 41.823881)')
# All transformation SQL will need to be performed on the
# _parent_ table.
- qs = PennsylvaniaCity.objects.transform(32128)
+ qs = PennsylvaniaCity.objects.annotate(new_point=functions.Transform('point', srid=32128))
self.assertEqual(1, qs.count())
for pc in qs:
- self.assertEqual(32128, pc.point.srid)
+ self.assertEqual(32128, pc.new_point.srid)
def test_raw_sql_query(self):
"Testing raw SQL query."
@@ -412,8 +413,8 @@ class GeoLookupTest(TestCase):
pnt1 = fromstr('POINT (649287.0363174 4177429.4494686)', srid=2847)
pnt2 = fromstr('POINT(-98.4919715741052 29.4333344025053)', srid=4326)
- # Not passing in a geometry as first param should
- # raise a type error when initializing the GeoQuerySet
+ # Not passing in a geometry as first param raises a TypeError when
+ # initializing the QuerySet.
with self.assertRaises(ValueError):
Country.objects.filter(mpoly__relate=(23, 'foo'))
@@ -451,66 +452,10 @@ class GeoLookupTest(TestCase):
@skipUnlessDBFeature("gis_enabled")
-@ignore_warnings(category=RemovedInDjango20Warning)
class GeoQuerySetTest(TestCase):
+ # TODO: GeoQuerySet is removed, organize these test better.
fixtures = ['initial']
- # Please keep the tests in GeoQuerySet method's alphabetic order
-
- @skipUnlessDBFeature("has_centroid_method")
- def test_centroid(self):
- "Testing the `centroid` GeoQuerySet method."
- qs = State.objects.exclude(poly__isnull=True).centroid()
- if oracle:
- tol = 0.1
- elif spatialite:
- tol = 0.000001
- else:
- tol = 0.000000001
- for s in qs:
- self.assertTrue(s.poly.centroid.equals_exact(s.centroid, tol))
-
- @skipUnlessDBFeature(
- "has_difference_method", "has_intersection_method",
- "has_sym_difference_method", "has_union_method")
- def test_diff_intersection_union(self):
- "Testing the `difference`, `intersection`, `sym_difference`, and `union` GeoQuerySet methods."
- geom = Point(5, 23)
- qs = Country.objects.all().difference(geom).sym_difference(geom).union(geom)
-
- # XXX For some reason SpatiaLite does something screwy with the Texas geometry here. Also,
- # XXX it doesn't like the null intersection.
- if spatialite:
- qs = qs.exclude(name='Texas')
- else:
- qs = qs.intersection(geom)
-
- for c in qs:
- if oracle:
- # Should be able to execute the queries; however, they won't be the same
- # as GEOS (because Oracle doesn't use GEOS internally like PostGIS or
- # SpatiaLite).
- pass
- else:
- if spatialite:
- # Spatialite `difference` doesn't have an SRID
- self.assertEqual(c.mpoly.difference(geom).wkt, c.difference.wkt)
- else:
- self.assertEqual(c.mpoly.difference(geom), c.difference)
- self.assertEqual(c.mpoly.intersection(geom), c.intersection)
- # Ordering might differ in collections
- self.assertSetEqual(set(g.wkt for g in c.mpoly.sym_difference(geom)),
- set(g.wkt for g in c.sym_difference))
- self.assertSetEqual(set(g.wkt for g in c.mpoly.union(geom)),
- set(g.wkt for g in c.union))
-
- @skipUnlessDBFeature("has_envelope_method")
- def test_envelope(self):
- "Testing the `envelope` GeoQuerySet method."
- countries = Country.objects.all().envelope()
- for country in countries:
- self.assertIsInstance(country.envelope, Polygon)
-
@skipUnlessDBFeature("supports_extent_aggr")
def test_extent(self):
"""
@@ -536,132 +481,6 @@ class GeoQuerySetTest(TestCase):
extent2 = City.objects.all()[:3].aggregate(Extent('point'))['point__extent']
self.assertNotEqual(extent1, extent2)
- @skipUnlessDBFeature("has_force_rhr_method")
- def test_force_rhr(self):
- "Testing GeoQuerySet.force_rhr()."
- rings = (
- ((0, 0), (5, 0), (0, 5), (0, 0)),
- ((1, 1), (1, 3), (3, 1), (1, 1)),
- )
- rhr_rings = (
- ((0, 0), (0, 5), (5, 0), (0, 0)),
- ((1, 1), (3, 1), (1, 3), (1, 1)),
- )
- State.objects.create(name='Foo', poly=Polygon(*rings))
- s = State.objects.force_rhr().get(name='Foo')
- self.assertEqual(rhr_rings, s.force_rhr.coords)
-
- @skipUnlessDBFeature("has_geohash_method")
- def test_geohash(self):
- "Testing GeoQuerySet.geohash()."
- # Reference query:
- # SELECT ST_GeoHash(point) FROM geoapp_city WHERE name='Houston';
- # SELECT ST_GeoHash(point, 5) FROM geoapp_city WHERE name='Houston';
- ref_hash = '9vk1mfq8jx0c8e0386z6'
- h1 = City.objects.geohash().get(name='Houston')
- h2 = City.objects.geohash(precision=5).get(name='Houston')
- self.assertEqual(ref_hash, h1.geohash)
- self.assertEqual(ref_hash[:5], h2.geohash)
-
- def test_geojson(self):
- "Testing GeoJSON output from the database using GeoQuerySet.geojson()."
- # Only PostGIS and SpatiaLite support GeoJSON.
- if not connection.ops.geojson:
- with self.assertRaises(NotImplementedError):
- Country.objects.all().geojson(field_name='mpoly')
- return
-
- pueblo_json = '{"type":"Point","coordinates":[-104.609252,38.255001]}'
- houston_json = (
- '{"type":"Point","crs":{"type":"name","properties":'
- '{"name":"EPSG:4326"}},"coordinates":[-95.363151,29.763374]}'
- )
- victoria_json = (
- '{"type":"Point","bbox":[-123.30519600,48.46261100,-123.30519600,48.46261100],'
- '"coordinates":[-123.305196,48.462611]}'
- )
- chicago_json = (
- '{"type":"Point","crs":{"type":"name","properties":{"name":"EPSG:4326"}},'
- '"bbox":[-87.65018,41.85039,-87.65018,41.85039],"coordinates":[-87.65018,41.85039]}'
- )
- if spatialite:
- victoria_json = (
- '{"type":"Point","bbox":[-123.305196,48.462611,-123.305196,48.462611],'
- '"coordinates":[-123.305196,48.462611]}'
- )
-
- # Precision argument should only be an integer
- with self.assertRaises(TypeError):
- City.objects.geojson(precision='foo')
-
- # Reference queries and values.
- # SELECT ST_AsGeoJson("geoapp_city"."point", 8, 0)
- # FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Pueblo';
- self.assertEqual(pueblo_json, City.objects.geojson().get(name='Pueblo').geojson)
-
- # SELECT ST_AsGeoJson("geoapp_city"."point", 8, 2) FROM "geoapp_city"
- # WHERE "geoapp_city"."name" = 'Houston';
- # This time we want to include the CRS by using the `crs` keyword.
- self.assertEqual(houston_json, City.objects.geojson(crs=True, model_att='json').get(name='Houston').json)
-
- # SELECT ST_AsGeoJson("geoapp_city"."point", 8, 1) FROM "geoapp_city"
- # WHERE "geoapp_city"."name" = 'Houston';
- # This time we include the bounding box by using the `bbox` keyword.
- self.assertEqual(victoria_json, City.objects.geojson(bbox=True).get(name='Victoria').geojson)
-
- # SELECT ST_AsGeoJson("geoapp_city"."point", 5, 3) FROM "geoapp_city"
- # WHERE "geoapp_city"."name" = 'Chicago';
- # Finally, we set every available keyword.
- self.assertEqual(
- chicago_json,
- City.objects.geojson(bbox=True, crs=True, precision=5).get(name='Chicago').geojson
- )
-
- @skipUnlessDBFeature("has_gml_method")
- def test_gml(self):
- "Testing GML output from the database using GeoQuerySet.gml()."
- # Should throw a TypeError when trying to obtain GML from a
- # non-geometry field.
- qs = City.objects.all()
- with self.assertRaises(TypeError):
- qs.gml(field_name='name')
- ptown1 = City.objects.gml(field_name='point', precision=9).get(name='Pueblo')
- ptown2 = City.objects.gml(precision=9).get(name='Pueblo')
-
- if oracle:
- # No precision parameter for Oracle :-/
- gml_regex = re.compile(
- r'^<gml:Point srsName="EPSG:4326" xmlns:gml="http://www.opengis.net/gml">'
- r'<gml:coordinates decimal="\." cs="," ts=" ">-104.60925\d+,38.25500\d+ '
- r'</gml:coordinates></gml:Point>'
- )
- else:
- gml_regex = re.compile(
- r'^<gml:Point srsName="EPSG:4326"><gml:coordinates>'
- r'-104\.60925\d+,38\.255001</gml:coordinates></gml:Point>'
- )
-
- for ptown in [ptown1, ptown2]:
- self.assertTrue(gml_regex.match(ptown.gml))
-
- if postgis:
- self.assertIn('<gml:pos srsDimension="2">', City.objects.gml(version=3).get(name='Pueblo').gml)
-
- @skipUnlessDBFeature("has_kml_method")
- def test_kml(self):
- "Testing KML output from the database using GeoQuerySet.kml()."
- # Should throw a TypeError when trying to obtain KML from a
- # non-geometry field.
- qs = City.objects.all()
- with self.assertRaises(TypeError):
- qs.kml('name')
-
- # Ensuring the KML is as expected.
- ptown1 = City.objects.kml(field_name='point', precision=9).get(name='Pueblo')
- ptown2 = City.objects.kml(precision=9).get(name='Pueblo')
- for ptown in [ptown1, ptown2]:
- self.assertEqual('<Point><coordinates>-104.609252,38.255001</coordinates></Point>', ptown.kml)
-
def test_make_line(self):
"""
Testing the `MakeLine` aggregate.
@@ -689,181 +508,6 @@ class GeoQuerySetTest(TestCase):
"%s != %s" % (ref_line, line)
)
- @skipUnlessDBFeature("has_num_geom_method")
- def test_num_geom(self):
- "Testing the `num_geom` GeoQuerySet method."
- # Both 'countries' only have two geometries.
- for c in Country.objects.num_geom():
- self.assertEqual(2, c.num_geom)
-
- for c in City.objects.filter(point__isnull=False).num_geom():
- # Oracle and PostGIS 2.0+ will return 1 for the number of
- # geometries on non-collections.
- self.assertEqual(1, c.num_geom)
-
- @skipUnlessDBFeature("supports_num_points_poly")
- def test_num_points(self):
- "Testing the `num_points` GeoQuerySet method."
- for c in Country.objects.num_points():
- self.assertEqual(c.mpoly.num_points, c.num_points)
-
- if not oracle:
- # Oracle cannot count vertices in Point geometries.
- for c in City.objects.num_points():
- self.assertEqual(1, c.num_points)
-
- @skipUnlessDBFeature("has_point_on_surface_method")
- def test_point_on_surface(self):
- "Testing the `point_on_surface` GeoQuerySet method."
- # Reference values.
- if oracle:
- # SELECT SDO_UTIL.TO_WKTGEOMETRY(SDO_GEOM.SDO_POINTONSURFACE(GEOAPP_COUNTRY.MPOLY, 0.05))
- # FROM GEOAPP_COUNTRY;
- ref = {'New Zealand': fromstr('POINT (174.616364 -36.100861)', srid=4326),
- 'Texas': fromstr('POINT (-103.002434 36.500397)', srid=4326),
- }
-
- else:
- # Using GEOSGeometry to compute the reference point on surface values
- # -- since PostGIS also uses GEOS these should be the same.
- ref = {'New Zealand': Country.objects.get(name='New Zealand').mpoly.point_on_surface,
- 'Texas': Country.objects.get(name='Texas').mpoly.point_on_surface
- }
-
- for c in Country.objects.point_on_surface():
- if spatialite:
- # XXX This seems to be a WKT-translation-related precision issue?
- tol = 0.00001
- else:
- tol = 0.000000001
- self.assertTrue(ref[c.name].equals_exact(c.point_on_surface, tol))
-
- @skipUnlessDBFeature("has_reverse_method")
- def test_reverse_geom(self):
- "Testing GeoQuerySet.reverse_geom()."
- coords = [(-95.363151, 29.763374), (-95.448601, 29.713803)]
- Track.objects.create(name='Foo', line=LineString(coords))
- t = Track.objects.reverse_geom().get(name='Foo')
- coords.reverse()
- self.assertEqual(tuple(coords), t.reverse_geom.coords)
- if oracle:
- with self.assertRaises(TypeError):
- State.objects.reverse_geom()
-
- @skipUnlessDBFeature("has_scale_method")
- def test_scale(self):
- "Testing the `scale` GeoQuerySet method."
- xfac, yfac = 2, 3
- tol = 5 # XXX The low precision tolerance is for SpatiaLite
- qs = Country.objects.scale(xfac, yfac, model_att='scaled')
- for c in qs:
- for p1, p2 in zip(c.mpoly, c.scaled):
- for r1, r2 in zip(p1, p2):
- for c1, c2 in zip(r1.coords, r2.coords):
- self.assertAlmostEqual(c1[0] * xfac, c2[0], tol)
- self.assertAlmostEqual(c1[1] * yfac, c2[1], tol)
-
- @skipUnlessDBFeature("has_snap_to_grid_method")
- def test_snap_to_grid(self):
- "Testing GeoQuerySet.snap_to_grid()."
- # Let's try and break snap_to_grid() with bad combinations of arguments.
- for bad_args in ((), range(3), range(5)):
- with self.assertRaises(ValueError):
- Country.objects.snap_to_grid(*bad_args)
- for bad_args in (('1.0',), (1.0, None), tuple(map(six.text_type, range(4)))):
- with self.assertRaises(TypeError):
- Country.objects.snap_to_grid(*bad_args)
-
- # Boundary for San Marino, courtesy of Bjorn Sandvik of thematicmapping.org
- # from the world borders dataset he provides.
- wkt = ('MULTIPOLYGON(((12.41580 43.95795,12.45055 43.97972,12.45389 43.98167,'
- '12.46250 43.98472,12.47167 43.98694,12.49278 43.98917,'
- '12.50555 43.98861,12.51000 43.98694,12.51028 43.98277,'
- '12.51167 43.94333,12.51056 43.93916,12.49639 43.92333,'
- '12.49500 43.91472,12.48778 43.90583,12.47444 43.89722,'
- '12.46472 43.89555,12.45917 43.89611,12.41639 43.90472,'
- '12.41222 43.90610,12.40782 43.91366,12.40389 43.92667,'
- '12.40500 43.94833,12.40889 43.95499,12.41580 43.95795)))')
- Country.objects.create(name='San Marino', mpoly=fromstr(wkt))
-
- # Because floating-point arithmetic isn't exact, we set a tolerance
- # to pass into GEOS `equals_exact`.
- tol = 0.000000001
-
- # SELECT AsText(ST_SnapToGrid("geoapp_country"."mpoly", 0.1)) FROM "geoapp_country"
- # WHERE "geoapp_country"."name" = 'San Marino';
- ref = fromstr('MULTIPOLYGON(((12.4 44,12.5 44,12.5 43.9,12.4 43.9,12.4 44)))')
- self.assertTrue(ref.equals_exact(Country.objects.snap_to_grid(0.1).get(name='San Marino').snap_to_grid, tol))
-
- # SELECT AsText(ST_SnapToGrid("geoapp_country"."mpoly", 0.05, 0.23)) FROM "geoapp_country"
- # WHERE "geoapp_country"."name" = 'San Marino';
- ref = fromstr('MULTIPOLYGON(((12.4 43.93,12.45 43.93,12.5 43.93,12.45 43.93,12.4 43.93)))')
- self.assertTrue(
- ref.equals_exact(Country.objects.snap_to_grid(0.05, 0.23).get(name='San Marino').snap_to_grid, tol)
- )
-
- # SELECT AsText(ST_SnapToGrid("geoapp_country"."mpoly", 0.5, 0.17, 0.05, 0.23)) FROM "geoapp_country"
- # WHERE "geoapp_country"."name" = 'San Marino';
- ref = fromstr(
- 'MULTIPOLYGON(((12.4 43.87,12.45 43.87,12.45 44.1,12.5 44.1,12.5 43.87,12.45 43.87,12.4 43.87)))'
- )
- self.assertTrue(
- ref.equals_exact(
- Country.objects.snap_to_grid(0.05, 0.23, 0.5, 0.17).get(name='San Marino').snap_to_grid,
- tol
- )
- )
-
- @skipUnlessDBFeature("has_svg_method")
- def test_svg(self):
- "Testing SVG output using GeoQuerySet.svg()."
-
- with self.assertRaises(TypeError):
- City.objects.svg(precision='foo')
- # SELECT AsSVG(geoapp_city.point, 0, 8) FROM geoapp_city WHERE name = 'Pueblo';
- svg1 = 'cx="-104.609252" cy="-38.255001"'
- # Even though relative, only one point so it's practically the same except for
- # the 'c' letter prefix on the x,y values.
- svg2 = svg1.replace('c', '')
- self.assertEqual(svg1, City.objects.svg().get(name='Pueblo').svg)
- self.assertEqual(svg2, City.objects.svg(relative=5).get(name='Pueblo').svg)
-
- @skipUnlessDBFeature("has_transform_method")
- def test_transform(self):
- "Testing the transform() GeoQuerySet method."
- # Pre-transformed points for Houston and Pueblo.
- htown = fromstr('POINT(1947516.83115183 6322297.06040572)', srid=3084)
- ptown = fromstr('POINT(992363.390841912 481455.395105533)', srid=2774)
- prec = 3 # Precision is low due to version variations in PROJ and GDAL.
-
- # Asserting the result of the transform operation with the values in
- # the pre-transformed points. Oracle does not have the 3084 SRID.
- if not oracle:
- h = City.objects.transform(htown.srid).get(name='Houston')
- self.assertEqual(3084, h.point.srid)
- self.assertAlmostEqual(htown.x, h.point.x, prec)
- self.assertAlmostEqual(htown.y, h.point.y, prec)
-
- p1 = City.objects.transform(ptown.srid, field_name='point').get(name='Pueblo')
- p2 = City.objects.transform(srid=ptown.srid).get(name='Pueblo')
- for p in [p1, p2]:
- self.assertEqual(2774, p.point.srid)
- self.assertAlmostEqual(ptown.x, p.point.x, prec)
- self.assertAlmostEqual(ptown.y, p.point.y, prec)
-
- @skipUnlessDBFeature("has_translate_method")
- def test_translate(self):
- "Testing the `translate` GeoQuerySet method."
- xfac, yfac = 5, -23
- qs = Country.objects.translate(xfac, yfac, model_att='translated')
- for c in qs:
- for p1, p2 in zip(c.mpoly, c.translated):
- for r1, r2 in zip(p1, p2):
- for c1, c2 in zip(r1.coords, r2.coords):
- # XXX The low precision is for SpatiaLite
- self.assertAlmostEqual(c1[0] + xfac, c2[0], 5)
- self.assertAlmostEqual(c1[1] + yfac, c2[1], 5)
-
@skipUnlessDBFeature('supports_union_aggr')
def test_unionagg(self):
"""
diff --git a/tests/gis_tests/geogapp/models.py b/tests/gis_tests/geogapp/models.py
index 3d2a12826a..6bc5955923 100644
--- a/tests/gis_tests/geogapp/models.py
+++ b/tests/gis_tests/geogapp/models.py
@@ -6,8 +6,6 @@ from django.utils.encoding import python_2_unicode_compatible
class NamedModel(models.Model):
name = models.CharField(max_length=30)
- objects = models.GeoManager()
-
class Meta:
abstract = True
required_db_features = ['gis_enabled']
diff --git a/tests/gis_tests/geogapp/tests.py b/tests/gis_tests/geogapp/tests.py
index 89a47405ce..d9f02184ea 100644
--- a/tests/gis_tests/geogapp/tests.py
+++ b/tests/gis_tests/geogapp/tests.py
@@ -11,11 +11,8 @@ from django.contrib.gis.db.models.functions import Area, Distance
from django.contrib.gis.measure import D
from django.db import connection
from django.db.models.functions import Cast
-from django.test import (
- TestCase, ignore_warnings, skipIfDBFeature, skipUnlessDBFeature,
-)
+from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
from django.utils._os import upath
-from django.utils.deprecation import RemovedInDjango20Warning
from ..utils import oracle, postgis, spatialite
from .models import City, County, Zipcode
@@ -32,7 +29,7 @@ class GeographyTest(TestCase):
@skipIf(spatialite, "SpatiaLite doesn't support distance lookups with Distance objects.")
@skipUnlessDBFeature("supports_distances_lookups", "supports_distance_geodetic")
def test02_distance_lookup(self):
- "Testing GeoQuerySet distance lookup support on non-point geography fields."
+ "Testing distance lookup support on non-point geography fields."
z = Zipcode.objects.get(code='77002')
cities1 = list(City.objects
.filter(point__distance_lte=(z.poly, D(mi=500)))
@@ -45,15 +42,6 @@ class GeographyTest(TestCase):
for cities in [cities1, cities2]:
self.assertEqual(['Dallas', 'Houston', 'Oklahoma City'], cities)
- @skipIf(spatialite, "distance() doesn't support geodetic coordinates on SpatiaLite.")
- @skipUnlessDBFeature("has_distance_method", "supports_distance_geodetic")
- @ignore_warnings(category=RemovedInDjango20Warning)
- def test03_distance_method(self):
- "Testing GeoQuerySet.distance() support on non-point geography fields."
- # `GeoQuerySet.distance` is not allowed geometry fields.
- htown = City.objects.get(name='Houston')
- Zipcode.objects.distance(htown.point)
-
@skipUnless(postgis, "This is a PostGIS-specific test")
def test04_invalid_operators_functions(self):
"Ensuring exceptions are raised for operators & functions invalid on geography fields."
@@ -101,19 +89,6 @@ class GeographyTest(TestCase):
self.assertEqual(name, c.name)
self.assertEqual(state, c.state)
- @skipIf(spatialite, "area() doesn't support geodetic coordinates on SpatiaLite.")
- @skipUnlessDBFeature("has_area_method", "supports_distance_geodetic")
- @ignore_warnings(category=RemovedInDjango20Warning)
- def test06_geography_area(self):
- "Testing that Area calculations work on geography columns."
- # SELECT ST_Area(poly) FROM geogapp_zipcode WHERE code='77002';
- z = Zipcode.objects.area().get(code='77002')
- # Round to the nearest thousand as possible values (depending on
- # the database and geolib) include 5439084, 5439100, 5439101.
- rounded_value = z.area.sq_m
- rounded_value -= z.area.sq_m % 1000
- self.assertEqual(rounded_value, 5439000)
-
@skipUnlessDBFeature("gis_enabled")
class GeographyFunctionTests(TestCase):
diff --git a/tests/gis_tests/relatedapp/models.py b/tests/gis_tests/relatedapp/models.py
index 32de25bd20..6d674588dd 100644
--- a/tests/gis_tests/relatedapp/models.py
+++ b/tests/gis_tests/relatedapp/models.py
@@ -3,9 +3,6 @@ from django.utils.encoding import python_2_unicode_compatible
class SimpleModel(models.Model):
-
- objects = models.GeoManager()
-
class Meta:
abstract = True
required_db_features = ['gis_enabled']
diff --git a/tests/gis_tests/relatedapp/tests.py b/tests/gis_tests/relatedapp/tests.py
index 3ca4d91dba..861b6ee2d9 100644
--- a/tests/gis_tests/relatedapp/tests.py
+++ b/tests/gis_tests/relatedapp/tests.py
@@ -38,33 +38,6 @@ class RelatedGeoModelTest(TestCase):
self.assertEqual(st, c.state)
self.assertEqual(Point(lon, lat, srid=c.location.point.srid), c.location.point)
- @skipUnlessDBFeature("has_transform_method")
- def test03_transform_related(self):
- "Testing the `transform` GeoQuerySet method on related geographic models."
- # All the transformations are to state plane coordinate systems using
- # US Survey Feet (thus a tolerance of 0 implies error w/in 1 survey foot).
- tol = 0
-
- def check_pnt(ref, pnt):
- self.assertAlmostEqual(ref.x, pnt.x, tol)
- self.assertAlmostEqual(ref.y, pnt.y, tol)
- self.assertEqual(ref.srid, pnt.srid)
-
- # Each city transformed to the SRID of their state plane coordinate system.
- transformed = (('Kecksburg', 2272, 'POINT(1490553.98959621 314792.131023984)'),
- ('Roswell', 2257, 'POINT(481902.189077221 868477.766629735)'),
- ('Aurora', 2276, 'POINT(2269923.2484839 7069381.28722222)'),
- )
-
- for name, srid, wkt in transformed:
- # Doing this implicitly sets `select_related` select the location.
- # TODO: Fix why this breaks on Oracle.
- qs = list(City.objects.filter(name=name).transform(srid, field_name='location__point'))
- check_pnt(GEOSGeometry(wkt, srid), qs[0].location.point)
-
- # Relations more than one level deep can be queried.
- self.assertEqual(list(Parcel.objects.transform(srid, field_name='city__location__point')), [])
-
@skipUnlessDBFeature("supports_extent_aggr")
def test_related_extent_aggregate(self):
"Testing the `Extent` aggregate on related geographic models."
@@ -190,13 +163,13 @@ class RelatedGeoModelTest(TestCase):
self.assertEqual('P1', qs[0].name)
def test07_values(self):
- "Testing values() and values_list() and GeoQuerySets."
+ "Testing values() and values_list()."
gqs = Location.objects.all()
gvqs = Location.objects.values()
gvlqs = Location.objects.values_list()
# Incrementing through each of the models, dictionaries, and tuples
- # returned by the different types of GeoQuerySets.
+ # returned by each QuerySet.
for m, d, t in zip(gqs, gvqs, gvlqs):
# The values should be Geometry objects and not raw strings returned
# by the spatial database.
@@ -234,7 +207,7 @@ class RelatedGeoModelTest(TestCase):
# TODO: fix on Oracle -- qs2 returns an empty result for an unknown reason
@no_oracle
def test10_combine(self):
- "Testing the combination of two GeoQuerySets. See #10807."
+ "Testing the combination of two QuerySets (#10807)."
buf1 = City.objects.get(name='Aurora').location.point.buffer(0.1)
buf2 = City.objects.get(name='Kecksburg').location.point.buffer(0.1)
qs1 = City.objects.filter(location__point__within=buf1)
diff --git a/tests/managers_regress/tests.py b/tests/managers_regress/tests.py
index 1ff34dede3..031c8a8155 100644
--- a/tests/managers_regress/tests.py
+++ b/tests/managers_regress/tests.py
@@ -305,19 +305,6 @@ class TestManagerInheritance(TestCase):
@isolate_apps('managers_regress')
class TestManagerDeprecations(TestCase):
- def test_use_for_related_fields_on_geomanager(self):
- from django.contrib.gis.db.models import GeoManager
-
- class MyModel(models.Model):
- objects = GeoManager()
-
- # Shouldn't issue any warnings, since GeoManager itself will be
- # deprecated at the same time as use_for_related_fields, there
- # is no point annoying users with this deprecation.
- with warnings.catch_warnings(record=True) as warns:
- warnings.simplefilter('always', RemovedInDjango20Warning)
- MyModel._base_manager
- self.assertEqual(len(warns), 0)
def test_use_for_related_fields_for_base_manager(self):
class MyManager(models.Manager):
diff --git a/tests/runtests.py b/tests/runtests.py
index 59f90646aa..6cec7d6e5c 100755
--- a/tests/runtests.py
+++ b/tests/runtests.py
@@ -168,12 +168,6 @@ def setup(verbosity, test_labels, parallel):
'fields.W901', # CommaSeparatedIntegerField deprecated
]
- warnings.filterwarnings(
- 'ignore',
- 'The GeoManager class is deprecated.',
- RemovedInDjango20Warning
- )
-
# Load all the ALWAYS_INSTALLED_APPS.
django.setup()