From a0d166306fbdc41f49e6fadf4ec84b17eb147daa Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Mon, 7 Nov 2016 13:00:40 +0100 Subject: [PATCH] Removed GeoManager and GeoQuerySet per deprecation timeline. --- .../contrib/gis/db/backends/base/features.py | 22 - .../contrib/gis/db/backends/oracle/models.py | 1 - django/contrib/gis/db/models/__init__.py | 3 +- django/contrib/gis/db/models/fields.py | 21 - django/contrib/gis/db/models/manager.py | 26 - django/contrib/gis/db/models/query.py | 727 ------------------ docs/ref/contrib/gis/geoquerysets.txt | 595 +------------- docs/ref/contrib/gis/model-api.txt | 16 - docs/ref/models/querysets.txt | 9 +- docs/releases/1.2.txt | 8 +- docs/releases/2.0.txt | 2 + tests/gis_tests/distapp/models.py | 2 - tests/gis_tests/distapp/tests.py | 215 +----- tests/gis_tests/geo3d/models.py | 2 - tests/gis_tests/geo3d/tests.py | 105 +-- tests/gis_tests/geoapp/models.py | 2 - tests/gis_tests/geoapp/test_functions.py | 2 - tests/gis_tests/geoapp/test_regress.py | 2 +- tests/gis_tests/geoapp/tests.py | 380 +-------- tests/gis_tests/geogapp/models.py | 2 - tests/gis_tests/geogapp/tests.py | 29 +- tests/gis_tests/relatedapp/models.py | 3 - tests/gis_tests/relatedapp/tests.py | 33 +- tests/managers_regress/tests.py | 13 - tests/runtests.py | 6 - 25 files changed, 32 insertions(+), 2194 deletions(-) delete mode 100644 django/contrib/gis/db/models/manager.py delete mode 100644 django/contrib/gis/db/models/query.py 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__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 ` - 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) - -147.78711,70.245363 ... -147.78711,70.245363 - -===================== ===================================================== -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) - -103.04135,36.217596,0 ... -103.04135,36.217596,0 - -===================== ===================================================== -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 `_. -``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 `. 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 `_. .. [#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('', 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('', 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'^-95.363\d+,29.763\d+,18$') - 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'^' - r'-104.60925\d+,38.25500\d+ ' - r'' - ) - else: - gml_regex = re.compile( - r'^' - r'-104\.60925\d+,38\.255001' - ) - - for ptown in [ptown1, ptown2]: - self.assertTrue(gml_regex.match(ptown.gml)) - - if postgis: - self.assertIn('', 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('-104.609252,38.255001', 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()