summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2018-01-27 11:12:11 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2018-01-27 11:14:42 +0100
commit42622b8934d46a8f07d1f89b66edbcffa98f3f4a (patch)
tree2fdc3af9f53263ebc46793bfed8b9757ce57612a
parent61c74ae74f6e23e5c6468c1bc2adb348c60cc289 (diff)
[2.0.x] Fixed #29054 -- Fixed a regression where a queryset that annotates with geometry objects crashes.
Made GEOSGeometryBase hashable. Regression in 19b2dfd1bfe7fd716dd3d8bfa5f972070d83b42f. Thanks Tim Graham for the review. Backport of b002a032f90b8cd228cfcee6c88cd238a8191cc0 from master
-rw-r--r--django/contrib/gis/geos/geometry.py3
-rw-r--r--docs/releases/2.0.2.txt3
-rw-r--r--tests/gis_tests/geoapp/test_expressions.py14
-rw-r--r--tests/gis_tests/geos_tests/test_geos.py16
4 files changed, 35 insertions, 1 deletions
diff --git a/django/contrib/gis/geos/geometry.py b/django/contrib/gis/geos/geometry.py
index bcda25fa2f..1ebecc864b 100644
--- a/django/contrib/gis/geos/geometry.py
+++ b/django/contrib/gis/geos/geometry.py
@@ -144,6 +144,9 @@ class GEOSGeometryBase(GEOSBase):
return False
return isinstance(other, GEOSGeometry) and self.srid == other.srid and self.equals_exact(other)
+ def __hash__(self):
+ return hash((self.srid, self.wkt))
+
# ### Geometry set-like operations ###
# Thanks to Sean Gillies for inspiration:
# http://lists.gispython.org/pipermail/community/2007-July/001034.html
diff --git a/docs/releases/2.0.2.txt b/docs/releases/2.0.2.txt
index 4a06ccb792..06968d4ba3 100644
--- a/docs/releases/2.0.2.txt
+++ b/docs/releases/2.0.2.txt
@@ -17,3 +17,6 @@ Bugfixes
* Fixed regression in the use of ``QuerySet.values_list(..., flat=True)``
followed by ``annotate()`` (:ticket:`29067`).
+
+* Fixed a regression where a queryset that annotates with geometry objects
+ crashes (:ticket:`29054`).
diff --git a/tests/gis_tests/geoapp/test_expressions.py b/tests/gis_tests/geoapp/test_expressions.py
index 496e6b58ce..2d0ebbcae0 100644
--- a/tests/gis_tests/geoapp/test_expressions.py
+++ b/tests/gis_tests/geoapp/test_expressions.py
@@ -3,10 +3,11 @@ from unittest import skipUnless
from django.contrib.gis.db.models import F, GeometryField, Value, functions
from django.contrib.gis.geos import Point, Polygon
from django.db import connection
+from django.db.models import Count
from django.test import TestCase, skipUnlessDBFeature
from ..utils import postgis
-from .models import City, ManyPointModel
+from .models import City, ManyPointModel, MultiFields
class GeoExpressionsTests(TestCase):
@@ -48,6 +49,17 @@ class GeoExpressionsTests(TestCase):
obj.refresh_from_db()
self.assertTrue(obj.point3.equals_exact(p1.transform(3857, clone=True), 0.1))
+ def test_multiple_annotation(self):
+ multi_field = MultiFields.objects.create(
+ point=Point(1, 1),
+ city=City.objects.get(name='Houston'),
+ poly=Polygon(((1, 1), (1, 2), (2, 2), (2, 1), (1, 1))),
+ )
+ qs = City.objects.values('name').annotate(
+ distance=functions.Distance('multifields__point', multi_field.city.point),
+ ).annotate(count=Count('multifields'))
+ self.assertTrue(qs.first())
+
@skipUnlessDBFeature('has_Translate_function')
def test_update_with_expression(self):
city = City.objects.create(point=Point(1, 1, srid=4326))
diff --git a/tests/gis_tests/geos_tests/test_geos.py b/tests/gis_tests/geos_tests/test_geos.py
index 0db98285fa..66574f16d1 100644
--- a/tests/gis_tests/geos_tests/test_geos.py
+++ b/tests/gis_tests/geos_tests/test_geos.py
@@ -187,6 +187,22 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
self.assertNotEqual(g, {'foo': 'bar'})
self.assertNotEqual(g, False)
+ def test_hash(self):
+ point_1 = Point(5, 23)
+ point_2 = Point(5, 23, srid=4326)
+ point_3 = Point(5, 23, srid=32632)
+ multipoint_1 = MultiPoint(point_1, srid=4326)
+ multipoint_2 = MultiPoint(point_2)
+ multipoint_3 = MultiPoint(point_3)
+ self.assertNotEqual(hash(point_1), hash(point_2))
+ self.assertNotEqual(hash(point_1), hash(point_3))
+ self.assertNotEqual(hash(point_2), hash(point_3))
+ self.assertNotEqual(hash(multipoint_1), hash(multipoint_2))
+ self.assertEqual(hash(multipoint_2), hash(multipoint_3))
+ self.assertNotEqual(hash(multipoint_1), hash(point_1))
+ self.assertNotEqual(hash(multipoint_2), hash(point_2))
+ self.assertNotEqual(hash(multipoint_3), hash(point_3))
+
def test_eq_with_srid(self):
"Testing non-equivalence with different srids."
p0 = Point(5, 23)