1
0
mirror of https://github.com/django/django.git synced 2025-10-31 09:41:08 +00:00

Fixed #34629 -- Added filtering support to GIS aggregates.

This commit is contained in:
Olivier Le Thanh Duong
2023-06-03 15:54:22 +02:00
committed by Mariusz Felisiak
parent c1cff3c471
commit 1b754d638d
7 changed files with 206 additions and 11 deletions

View File

@@ -135,5 +135,53 @@
"title": "Patry on Copyright",
"author": 2
}
}
]
},
{
"model": "relatedapp.parcel",
"pk": 1,
"fields": {
"name": "Aurora Parcel Alpha",
"city": 1,
"center1": "POINT (1.7128 -2.0060)",
"center2": "POINT (3.7128 -5.0060)",
"border1": "POLYGON((0 0, 5 5, 12 12, 0 0))",
"border2": "POLYGON((0 0, 5 5, 8 8, 0 0))"
}
},
{
"model": "relatedapp.parcel",
"pk": 2,
"fields": {
"name": "Aurora Parcel Beta",
"city": 1,
"center1": "POINT (4.7128 5.0060)",
"center2": "POINT (12.75 10.05)",
"border1": "POLYGON((10 10, 15 15, 22 22, 10 10))",
"border2": "POLYGON((10 10, 15 15, 22 22, 10 10))"
}
},
{
"model": "relatedapp.parcel",
"pk": 3,
"fields": {
"name": "Aurora Parcel Ignore",
"city": 1,
"center1": "POINT (9.7128 12.0060)",
"center2": "POINT (1.7128 -2.0060)",
"border1": "POLYGON ((24 23, 25 25, 32 32, 24 23))",
"border2": "POLYGON ((24 23, 25 25, 32 32, 24 23))"
}
},
{
"model": "relatedapp.parcel",
"pk": 4,
"fields": {
"name": "Roswell Parcel Ignore",
"city": 2,
"center1": "POINT (-9.7128 -12.0060)",
"center2": "POINT (-1.7128 2.0060)",
"border1": "POLYGON ((30 30, 35 35, 42 32, 30 30))",
"border2": "POLYGON ((30 30, 35 35, 42 32, 30 30))"
}
}
]

View File

@@ -1,4 +1,5 @@
from django.contrib.gis.db.models import Collect, Count, Extent, F, Union
from django.contrib.gis.db.models import Collect, Count, Extent, F, MakeLine, Q, Union
from django.contrib.gis.db.models.functions import Centroid
from django.contrib.gis.geos import GEOSGeometry, MultiPoint, Point
from django.db import NotSupportedError, connection
from django.test import TestCase, skipUnlessDBFeature
@@ -304,6 +305,116 @@ class RelatedGeoModelTest(TestCase):
self.assertEqual(4, len(coll))
self.assertTrue(ref_geom.equals(coll))
@skipUnlessDBFeature("supports_collect_aggr")
def test_collect_filter(self):
qs = City.objects.annotate(
parcel_center=Collect(
"parcel__center1",
filter=~Q(parcel__name__icontains="ignore"),
),
parcel_center_nonexistent=Collect(
"parcel__center1",
filter=Q(parcel__name__icontains="nonexistent"),
),
parcel_center_single=Collect(
"parcel__center1",
filter=Q(parcel__name__contains="Alpha"),
),
)
city = qs.get(name="Aurora")
self.assertEqual(
city.parcel_center.wkt, "MULTIPOINT (1.7128 -2.006, 4.7128 5.006)"
)
self.assertIsNone(city.parcel_center_nonexistent)
self.assertIn(
city.parcel_center_single.wkt,
[
"MULTIPOINT (1.7128 -2.006)",
"POINT (1.7128 -2.006)", # SpatiaLite collapse to POINT.
],
)
@skipUnlessDBFeature("has_Centroid_function", "supports_collect_aggr")
def test_centroid_collect_filter(self):
qs = City.objects.annotate(
parcel_centroid=Centroid(
Collect(
"parcel__center1",
filter=~Q(parcel__name__icontains="ignore"),
)
)
)
city = qs.get(name="Aurora")
self.assertEqual(city.parcel_centroid.wkt, "POINT (3.2128 1.5)")
@skipUnlessDBFeature("supports_make_line_aggr")
def test_make_line_filter(self):
qs = City.objects.annotate(
parcel_line=MakeLine(
"parcel__center1",
filter=~Q(parcel__name__icontains="ignore"),
),
parcel_line_nonexistent=MakeLine(
"parcel__center1",
filter=Q(parcel__name__icontains="nonexistent"),
),
)
city = qs.get(name="Aurora")
self.assertIn(
city.parcel_line.wkt,
# The default ordering is flaky, so check both.
[
"LINESTRING (1.7128 -2.006, 4.7128 5.006)",
"LINESTRING (4.7128 5.006, 1.7128 -2.006)",
],
)
self.assertIsNone(city.parcel_line_nonexistent)
@skipUnlessDBFeature("supports_extent_aggr")
def test_extent_filter(self):
qs = City.objects.annotate(
parcel_border=Extent(
"parcel__border1",
filter=~Q(parcel__name__icontains="ignore"),
),
parcel_border_nonexistent=Extent(
"parcel__border1",
filter=Q(parcel__name__icontains="nonexistent"),
),
parcel_border_no_filter=Extent("parcel__border1"),
)
city = qs.get(name="Aurora")
self.assertEqual(city.parcel_border, (0.0, 0.0, 22.0, 22.0))
self.assertIsNone(city.parcel_border_nonexistent)
self.assertEqual(city.parcel_border_no_filter, (0.0, 0.0, 32.0, 32.0))
@skipUnlessDBFeature("supports_union_aggr")
def test_union_filter(self):
qs = City.objects.annotate(
parcel_point_union=Union(
"parcel__center2",
filter=~Q(parcel__name__icontains="ignore"),
),
parcel_point_nonexistent=Union(
"parcel__center2",
filter=Q(parcel__name__icontains="nonexistent"),
),
parcel_point_union_single=Union(
"parcel__center2",
filter=Q(parcel__name__contains="Alpha"),
),
)
city = qs.get(name="Aurora")
self.assertIn(
city.parcel_point_union.wkt,
[
"MULTIPOINT (12.75 10.05, 3.7128 -5.006)",
"MULTIPOINT (3.7128 -5.006, 12.75 10.05)",
],
)
self.assertIsNone(city.parcel_point_nonexistent)
self.assertEqual(city.parcel_point_union_single.wkt, "POINT (3.7128 -5.006)")
def test15_invalid_select_related(self):
"""
select_related on the related name manager of a unique FK.