Deprecated legacy GeoManager/GeoQuerySet methods
This commit is contained in:
parent
71e20814fc
commit
ea27e26b09
|
@ -1,5 +1,8 @@
|
||||||
|
import warnings
|
||||||
|
|
||||||
from django.contrib.gis.db.models.query import GeoQuerySet
|
from django.contrib.gis.db.models.query import GeoQuerySet
|
||||||
from django.db.models.manager import Manager
|
from django.db.models.manager import Manager
|
||||||
|
from django.utils.deprecation import RemovedInDjango21Warning
|
||||||
|
|
||||||
|
|
||||||
class GeoManager(Manager.from_queryset(GeoQuerySet)):
|
class GeoManager(Manager.from_queryset(GeoQuerySet)):
|
||||||
|
@ -9,3 +12,11 @@ class GeoManager(Manager.from_queryset(GeoQuerySet)):
|
||||||
# so that geometry columns on Oracle and MySQL are selected
|
# so that geometry columns on Oracle and MySQL are selected
|
||||||
# properly.
|
# properly.
|
||||||
use_for_related_fields = True
|
use_for_related_fields = 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.",
|
||||||
|
RemovedInDjango21Warning, stacklevel=2
|
||||||
|
)
|
||||||
|
super(GeoManager, self).__init__(*args, **kwargs)
|
||||||
|
|
|
@ -15,7 +15,9 @@ from django.db.models.expressions import RawSQL
|
||||||
from django.db.models.fields import Field
|
from django.db.models.fields import Field
|
||||||
from django.db.models.query import QuerySet
|
from django.db.models.query import QuerySet
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from django.utils.deprecation import RemovedInDjango20Warning
|
from django.utils.deprecation import (
|
||||||
|
RemovedInDjango20Warning, RemovedInDjango21Warning,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class GeoQuerySet(QuerySet):
|
class GeoQuerySet(QuerySet):
|
||||||
|
@ -513,6 +515,11 @@ class GeoQuerySet(QuerySet):
|
||||||
The name of the model attribute to attach the output of
|
The name of the model attribute to attach the output of
|
||||||
the spatial function to.
|
the spatial function to.
|
||||||
"""
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
"The %s GeoQuerySet method is deprecated. See GeoDjango Functions "
|
||||||
|
"documentation to find the expression-based replacement." % att,
|
||||||
|
RemovedInDjango21Warning, stacklevel=2
|
||||||
|
)
|
||||||
# Default settings.
|
# Default settings.
|
||||||
settings.setdefault('desc', None)
|
settings.setdefault('desc', None)
|
||||||
settings.setdefault('geom_args', ())
|
settings.setdefault('geom_args', ())
|
||||||
|
|
|
@ -2,6 +2,7 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.contrib.gis.db.models.fields import GeometryField
|
from django.contrib.gis.db.models.fields import GeometryField
|
||||||
|
from django.contrib.gis.db.models.functions import AsKML, Transform
|
||||||
from django.contrib.gis.shortcuts import render_to_kml, render_to_kmz
|
from django.contrib.gis.shortcuts import render_to_kml, render_to_kmz
|
||||||
from django.core.exceptions import FieldDoesNotExist
|
from django.core.exceptions import FieldDoesNotExist
|
||||||
from django.db import DEFAULT_DB_ALIAS, connections
|
from django.db import DEFAULT_DB_ALIAS, connections
|
||||||
|
@ -31,15 +32,17 @@ def kml(request, label, model, field_name=None, compress=False, using=DEFAULT_DB
|
||||||
|
|
||||||
connection = connections[using]
|
connection = connections[using]
|
||||||
|
|
||||||
if connection.features.has_kml_method:
|
if connection.features.has_AsKML_function:
|
||||||
# Database will take care of transformation.
|
# Database will take care of transformation.
|
||||||
placemarks = klass._default_manager.using(using).kml(field_name=field_name)
|
placemarks = klass._default_manager.using(using).annotate(kml=AsKML(field_name))
|
||||||
else:
|
else:
|
||||||
# If the database offers no KML method, we use the `kml`
|
# If the database offers no KML method, we use the `kml`
|
||||||
# attribute of the lazy geometry instead.
|
# attribute of the lazy geometry instead.
|
||||||
placemarks = []
|
placemarks = []
|
||||||
if connection.features.has_transform_method:
|
if connection.features.has_Transform_function:
|
||||||
qs = klass._default_manager.using(using).transform(4326, field_name=field_name)
|
qs = klass._default_manager.using(using).annotate(
|
||||||
|
**{'%s_4326' % field_name: Transform(field_name, 4326)})
|
||||||
|
field_name += '_4326'
|
||||||
else:
|
else:
|
||||||
qs = klass._default_manager.using(using).all()
|
qs = klass._default_manager.using(using).all()
|
||||||
for mod in qs:
|
for mod in qs:
|
||||||
|
|
|
@ -35,6 +35,8 @@ details on these changes.
|
||||||
* The ``django.contrib.auth.tests.utils.skipIfCustomUser()`` decorator will be
|
* The ``django.contrib.auth.tests.utils.skipIfCustomUser()`` decorator will be
|
||||||
removed.
|
removed.
|
||||||
|
|
||||||
|
* The ``GeoManager`` and ``GeoQuerySet`` classes will be removed.
|
||||||
|
|
||||||
.. _deprecation-removed-in-2.0:
|
.. _deprecation-removed-in-2.0:
|
||||||
|
|
||||||
2.0
|
2.0
|
||||||
|
|
|
@ -400,6 +400,16 @@ of its methods and attributes are either changed or renamed.
|
||||||
|
|
||||||
The aim of these changes is to provide a documented API for relation fields.
|
The aim of these changes is to provide a documented API for relation fields.
|
||||||
|
|
||||||
|
``GeoManager`` and ``GeoQuerySet`` custom methods
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
All custom ``GeoQuerySet`` methods (``area()``, ``distance()``, ``gml()``, ...)
|
||||||
|
have been replaced by equivalent geographic expressions in annotations (see in
|
||||||
|
new features). Hence the need to set a custom ``GeoManager`` to GIS-enabled
|
||||||
|
models is now obsolete. As soon as your code doesn't call any of the deprecated
|
||||||
|
methods, you can simply remove the ``objects = GeoManager()`` lines from your
|
||||||
|
models.
|
||||||
|
|
||||||
Miscellaneous
|
Miscellaneous
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@ from django.contrib.gis.geos import HAS_GEOS
|
||||||
from django.contrib.gis.measure import D # alias for Distance
|
from django.contrib.gis.measure import D # alias for Distance
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.test import TestCase, skipUnlessDBFeature
|
from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
|
||||||
|
from django.utils.deprecation import RemovedInDjango21Warning
|
||||||
|
|
||||||
from ..utils import no_oracle, oracle, postgis, spatialite
|
from ..utils import no_oracle, oracle, postgis, spatialite
|
||||||
|
|
||||||
|
@ -98,6 +99,7 @@ class DistanceTest(TestCase):
|
||||||
self.assertListEqual(au_cities, self.get_names(qs.filter(point__dwithin=(self.au_pnt, dist))))
|
self.assertListEqual(au_cities, self.get_names(qs.filter(point__dwithin=(self.au_pnt, dist))))
|
||||||
|
|
||||||
@skipUnlessDBFeature("has_distance_method")
|
@skipUnlessDBFeature("has_distance_method")
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
def test_distance_projected(self):
|
def test_distance_projected(self):
|
||||||
"""
|
"""
|
||||||
Test the `distance` GeoQuerySet method on projected coordinate systems.
|
Test the `distance` GeoQuerySet method on projected coordinate systems.
|
||||||
|
@ -141,6 +143,7 @@ class DistanceTest(TestCase):
|
||||||
self.assertAlmostEqual(ft_distances[i], c.distance.survey_ft, tol)
|
self.assertAlmostEqual(ft_distances[i], c.distance.survey_ft, tol)
|
||||||
|
|
||||||
@skipUnlessDBFeature("has_distance_method", "supports_distance_geodetic")
|
@skipUnlessDBFeature("has_distance_method", "supports_distance_geodetic")
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
def test_distance_geodetic(self):
|
def test_distance_geodetic(self):
|
||||||
"""
|
"""
|
||||||
Test the `distance` GeoQuerySet method on geodetic coordinate systems.
|
Test the `distance` GeoQuerySet method on geodetic coordinate systems.
|
||||||
|
@ -202,6 +205,7 @@ class DistanceTest(TestCase):
|
||||||
|
|
||||||
@no_oracle # Oracle already handles geographic distance calculation.
|
@no_oracle # Oracle already handles geographic distance calculation.
|
||||||
@skipUnlessDBFeature("has_distance_method")
|
@skipUnlessDBFeature("has_distance_method")
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
def test_distance_transform(self):
|
def test_distance_transform(self):
|
||||||
"""
|
"""
|
||||||
Test the `distance` GeoQuerySet method used with `transform` on a geographic field.
|
Test the `distance` GeoQuerySet method used with `transform` on a geographic field.
|
||||||
|
@ -322,6 +326,7 @@ class DistanceTest(TestCase):
|
||||||
self.assertEqual(cities, ['Adelaide', 'Hobart', 'Shellharbour', 'Thirroul'])
|
self.assertEqual(cities, ['Adelaide', 'Hobart', 'Shellharbour', 'Thirroul'])
|
||||||
|
|
||||||
@skipUnlessDBFeature("has_area_method")
|
@skipUnlessDBFeature("has_area_method")
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
def test_area(self):
|
def test_area(self):
|
||||||
"""
|
"""
|
||||||
Test the `area` GeoQuerySet method.
|
Test the `area` GeoQuerySet method.
|
||||||
|
@ -335,6 +340,7 @@ class DistanceTest(TestCase):
|
||||||
self.assertAlmostEqual(area_sq_m[i], z.area.sq_m, tol)
|
self.assertAlmostEqual(area_sq_m[i], z.area.sq_m, tol)
|
||||||
|
|
||||||
@skipUnlessDBFeature("has_length_method")
|
@skipUnlessDBFeature("has_length_method")
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
def test_length(self):
|
def test_length(self):
|
||||||
"""
|
"""
|
||||||
Test the `length` GeoQuerySet method.
|
Test the `length` GeoQuerySet method.
|
||||||
|
@ -358,6 +364,7 @@ class DistanceTest(TestCase):
|
||||||
self.assertAlmostEqual(len_m2, i10.length.m, 2)
|
self.assertAlmostEqual(len_m2, i10.length.m, 2)
|
||||||
|
|
||||||
@skipUnlessDBFeature("has_perimeter_method")
|
@skipUnlessDBFeature("has_perimeter_method")
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
def test_perimeter(self):
|
def test_perimeter(self):
|
||||||
"""
|
"""
|
||||||
Test the `perimeter` GeoQuerySet method.
|
Test the `perimeter` GeoQuerySet method.
|
||||||
|
@ -374,6 +381,7 @@ class DistanceTest(TestCase):
|
||||||
self.assertEqual(0, c.perim.m)
|
self.assertEqual(0, c.perim.m)
|
||||||
|
|
||||||
@skipUnlessDBFeature("has_area_method", "has_distance_method")
|
@skipUnlessDBFeature("has_area_method", "has_distance_method")
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
def test_measurement_null_fields(self):
|
def test_measurement_null_fields(self):
|
||||||
"""
|
"""
|
||||||
Test the measurement GeoQuerySet methods on fields with NULL values.
|
Test the measurement GeoQuerySet methods on fields with NULL values.
|
||||||
|
@ -388,6 +396,7 @@ class DistanceTest(TestCase):
|
||||||
self.assertIsNone(z.area)
|
self.assertIsNone(z.area)
|
||||||
|
|
||||||
@skipUnlessDBFeature("has_distance_method")
|
@skipUnlessDBFeature("has_distance_method")
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
def test_distance_order_by(self):
|
def test_distance_order_by(self):
|
||||||
qs = SouthTexasCity.objects.distance(Point(3, 3)).order_by(
|
qs = SouthTexasCity.objects.distance(Point(3, 3)).order_by(
|
||||||
'distance'
|
'distance'
|
||||||
|
|
|
@ -11,7 +11,9 @@ from django.contrib.gis.gdal import HAS_GDAL
|
||||||
from django.contrib.gis.geos import HAS_GEOS
|
from django.contrib.gis.geos import HAS_GEOS
|
||||||
from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
|
from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
from django.utils.deprecation import RemovedInDjango20Warning
|
from django.utils.deprecation import (
|
||||||
|
RemovedInDjango20Warning, RemovedInDjango21Warning,
|
||||||
|
)
|
||||||
|
|
||||||
if HAS_GEOS:
|
if HAS_GEOS:
|
||||||
from django.contrib.gis.db.models import Union, Extent3D
|
from django.contrib.gis.db.models import Union, Extent3D
|
||||||
|
@ -172,6 +174,7 @@ class Geo3DTest(Geo3DLoadingHelper, TestCase):
|
||||||
lm.save()
|
lm.save()
|
||||||
self.assertEqual(3, MultiPoint3D.objects.count())
|
self.assertEqual(3, MultiPoint3D.objects.count())
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
def test_kml(self):
|
def test_kml(self):
|
||||||
"""
|
"""
|
||||||
Test GeoQuerySet.kml() with Z values.
|
Test GeoQuerySet.kml() with Z values.
|
||||||
|
@ -183,6 +186,7 @@ class Geo3DTest(Geo3DLoadingHelper, TestCase):
|
||||||
ref_kml_regex = re.compile(r'^<Point><coordinates>-95.363\d+,29.763\d+,18</coordinates></Point>$')
|
ref_kml_regex = re.compile(r'^<Point><coordinates>-95.363\d+,29.763\d+,18</coordinates></Point>$')
|
||||||
self.assertTrue(ref_kml_regex.match(h.kml))
|
self.assertTrue(ref_kml_regex.match(h.kml))
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
def test_geojson(self):
|
def test_geojson(self):
|
||||||
"""
|
"""
|
||||||
Test GeoQuerySet.geojson() with Z values.
|
Test GeoQuerySet.geojson() with Z values.
|
||||||
|
@ -234,6 +238,7 @@ class Geo3DTest(Geo3DLoadingHelper, TestCase):
|
||||||
self.assertIsNone(City3D.objects.none().extent3d())
|
self.assertIsNone(City3D.objects.none().extent3d())
|
||||||
self.assertIsNone(City3D.objects.none().aggregate(Extent3D('point'))['point__extent3d'])
|
self.assertIsNone(City3D.objects.none().aggregate(Extent3D('point'))['point__extent3d'])
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
@skipUnlessDBFeature("supports_3d_functions")
|
@skipUnlessDBFeature("supports_3d_functions")
|
||||||
def test_perimeter(self):
|
def test_perimeter(self):
|
||||||
"""
|
"""
|
||||||
|
@ -252,6 +257,7 @@ class Geo3DTest(Geo3DLoadingHelper, TestCase):
|
||||||
Polygon3D.objects.perimeter().get(name='3D BBox').perimeter.m,
|
Polygon3D.objects.perimeter().get(name='3D BBox').perimeter.m,
|
||||||
tol)
|
tol)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
@skipUnlessDBFeature("supports_3d_functions")
|
@skipUnlessDBFeature("supports_3d_functions")
|
||||||
def test_length(self):
|
def test_length(self):
|
||||||
"""
|
"""
|
||||||
|
@ -285,6 +291,7 @@ class Geo3DTest(Geo3DLoadingHelper, TestCase):
|
||||||
InterstateProj3D.objects.length().get(name='I-45').length.m,
|
InterstateProj3D.objects.length().get(name='I-45').length.m,
|
||||||
tol)
|
tol)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
@skipUnlessDBFeature("supports_3d_functions")
|
@skipUnlessDBFeature("supports_3d_functions")
|
||||||
def test_scale(self):
|
def test_scale(self):
|
||||||
"""
|
"""
|
||||||
|
@ -297,6 +304,7 @@ class Geo3DTest(Geo3DLoadingHelper, TestCase):
|
||||||
for city in City3D.objects.scale(1.0, 1.0, zscale):
|
for city in City3D.objects.scale(1.0, 1.0, zscale):
|
||||||
self.assertEqual(city_dict[city.name][2] * zscale, city.scale.z)
|
self.assertEqual(city_dict[city.name][2] * zscale, city.scale.z)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
@skipUnlessDBFeature("supports_3d_functions")
|
@skipUnlessDBFeature("supports_3d_functions")
|
||||||
def test_translate(self):
|
def test_translate(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -9,7 +9,9 @@ from django.core.management import call_command
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
|
from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from django.utils.deprecation import RemovedInDjango20Warning
|
from django.utils.deprecation import (
|
||||||
|
RemovedInDjango20Warning, RemovedInDjango21Warning,
|
||||||
|
)
|
||||||
|
|
||||||
from ..utils import no_oracle, oracle, postgis, spatialite
|
from ..utils import no_oracle, oracle, postgis, spatialite
|
||||||
|
|
||||||
|
@ -431,6 +433,7 @@ class GeoLookupTest(TestCase):
|
||||||
|
|
||||||
|
|
||||||
@skipUnlessDBFeature("gis_enabled")
|
@skipUnlessDBFeature("gis_enabled")
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
class GeoQuerySetTest(TestCase):
|
class GeoQuerySetTest(TestCase):
|
||||||
fixtures = ['initial']
|
fixtures = ['initial']
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,9 @@ from django.contrib.gis.db.models.functions import Area, Distance
|
||||||
from django.contrib.gis.gdal import HAS_GDAL
|
from django.contrib.gis.gdal import HAS_GDAL
|
||||||
from django.contrib.gis.geos import HAS_GEOS
|
from django.contrib.gis.geos import HAS_GEOS
|
||||||
from django.contrib.gis.measure import D
|
from django.contrib.gis.measure import D
|
||||||
from django.test import TestCase, skipUnlessDBFeature
|
from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
|
from django.utils.deprecation import RemovedInDjango21Warning
|
||||||
|
|
||||||
from ..utils import oracle, postgis
|
from ..utils import oracle, postgis
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ class GeographyTest(TestCase):
|
||||||
self.assertEqual(['Dallas', 'Houston', 'Oklahoma City'], cities)
|
self.assertEqual(['Dallas', 'Houston', 'Oklahoma City'], cities)
|
||||||
|
|
||||||
@skipUnlessDBFeature("has_distance_method", "supports_distance_geodetic")
|
@skipUnlessDBFeature("has_distance_method", "supports_distance_geodetic")
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
def test03_distance_method(self):
|
def test03_distance_method(self):
|
||||||
"Testing GeoQuerySet.distance() support on non-point geography fields."
|
"Testing GeoQuerySet.distance() support on non-point geography fields."
|
||||||
# `GeoQuerySet.distance` is not allowed geometry fields.
|
# `GeoQuerySet.distance` is not allowed geometry fields.
|
||||||
|
@ -95,6 +97,7 @@ class GeographyTest(TestCase):
|
||||||
self.assertEqual(state, c.state)
|
self.assertEqual(state, c.state)
|
||||||
|
|
||||||
@skipUnlessDBFeature("has_area_method", "supports_distance_geodetic")
|
@skipUnlessDBFeature("has_area_method", "supports_distance_geodetic")
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
def test06_geography_area(self):
|
def test06_geography_area(self):
|
||||||
"Testing that Area calculations work on geography columns."
|
"Testing that Area calculations work on geography columns."
|
||||||
# SELECT ST_Area(poly) FROM geogapp_zipcode WHERE code='77002';
|
# SELECT ST_Area(poly) FROM geogapp_zipcode WHERE code='77002';
|
||||||
|
|
|
@ -158,6 +158,11 @@ def setup(verbosity, test_labels):
|
||||||
'django.contrib.webdesign will be removed in Django 2.0.',
|
'django.contrib.webdesign will be removed in Django 2.0.',
|
||||||
RemovedInDjango20Warning
|
RemovedInDjango20Warning
|
||||||
)
|
)
|
||||||
|
warnings.filterwarnings(
|
||||||
|
'ignore',
|
||||||
|
'The GeoManager class is deprecated.',
|
||||||
|
RemovedInDjango21Warning
|
||||||
|
)
|
||||||
|
|
||||||
# Load all the ALWAYS_INSTALLED_APPS.
|
# Load all the ALWAYS_INSTALLED_APPS.
|
||||||
django.setup()
|
django.setup()
|
||||||
|
|
Loading…
Reference in New Issue