[2.0.x] Fixed #29054 -- Fixed a regression where a queryset that annotates with geometry objects crashes.

Made GEOSGeometryBase hashable.
Regression in 19b2dfd1bf.

Thanks Tim Graham for the review.
Backport of b002a032f9 from master
This commit is contained in:
Mariusz Felisiak 2018-01-27 11:12:11 +01:00
parent 61c74ae74f
commit 42622b8934
No known key found for this signature in database
GPG Key ID: 2EF56372BA48CD1B
4 changed files with 35 additions and 1 deletions

View File

@ -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

View File

@ -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`).

View File

@ -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))

View File

@ -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)