Skip to content

Commit fc3bf2c

Browse files
committed
Address Tim review
1 parent 5ad9f60 commit fc3bf2c

File tree

6 files changed

+176
-42
lines changed

6 files changed

+176
-42
lines changed

django_mongodb_backend/gis/features.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
class GISFeatures(BaseSpatialFeatures):
66
has_spatialrefsys_table = False
7-
supports_transform = False
87
supports_distance_geodetic = False
8+
supports_transform = False
99

1010
@cached_property
1111
def django_test_expected_failures(self):

django_mongodb_backend/gis/lookups.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from django_mongodb_backend.query_utils import process_lhs, process_rhs
55

66

7-
def _gis_lookup(self, compiler, connection, as_expr=False):
7+
def gis_lookup(self, compiler, connection, as_expr=False):
88
lhs_mql = process_lhs(self, compiler, connection, as_expr=as_expr)
99
rhs_mql = process_rhs(self, compiler, connection, as_expr=as_expr)
1010
try:
@@ -15,5 +15,5 @@ def _gis_lookup(self, compiler, connection, as_expr=False):
1515

1616

1717
def register_lookups():
18-
GISLookup.as_mql = _gis_lookup
19-
DistanceLookupFromFunction.as_mql = _gis_lookup
18+
GISLookup.as_mql = gis_lookup
19+
DistanceLookupFromFunction.as_mql = gis_lookup

django_mongodb_backend/gis/operations.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ def get_distance(self, f, value, lookup_type):
205205
if isinstance(value, Distance):
206206
if f.geodetic(self.connection):
207207
raise ValueError(
208-
"Only numeric values of degree units are allowed on geodetic distance queries."
208+
"Only numeric values of radian units are allowed on geodetic distance queries."
209209
)
210210
dist_param = getattr(value, Distance.unit_attname(f.units_name(self.connection)))
211211
else:
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
[
2+
{
3+
"pk": "000000000000000000000001",
4+
"model": "gis_tests_.city",
5+
"fields": {
6+
"name": "Houston",
7+
"point": "POINT (-95.363151 29.763374)"
8+
}
9+
},
10+
{
11+
"pk": "000000000000000000000002",
12+
"model": "gis_tests_.city",
13+
"fields": {
14+
"name": "Dallas",
15+
"point": "POINT (-96.801611 32.782057)"
16+
}
17+
},
18+
{
19+
"pk": "000000000000000000000003",
20+
"model": "gis_tests_.city",
21+
"fields": {
22+
"name": "Oklahoma City",
23+
"point": "POINT (-97.521157 34.464642)"
24+
}
25+
},
26+
{
27+
"pk": "000000000000000000000004",
28+
"model": "gis_tests_.city",
29+
"fields": {
30+
"name": "Wellington",
31+
"point": "POINT (174.783117 -41.315268)"
32+
}
33+
},
34+
{
35+
"pk": "000000000000000000000005",
36+
"model": "gis_tests_.city",
37+
"fields": {
38+
"name": "Pueblo",
39+
"point": "POINT (-104.609252 38.255001)"
40+
}
41+
},
42+
{
43+
"pk": "000000000000000000000006",
44+
"model": "gis_tests_.city",
45+
"fields": {
46+
"name": "Lawrence",
47+
"point": "POINT (-95.235060 38.971823)"
48+
}
49+
},
50+
{
51+
"pk": "000000000000000000000007",
52+
"model": "gis_tests_.city",
53+
"fields": {
54+
"name": "Chicago",
55+
"point": "POINT (-87.650175 41.850385)"
56+
}
57+
},
58+
{
59+
"pk": "000000000000000000000008",
60+
"model": "gis_tests_.city",
61+
"fields": {
62+
"name": "Victoria",
63+
"point": "POINT (-123.305196 48.462611)"
64+
}
65+
},
66+
{
67+
"pk": "000000000000000000000001",
68+
"model": "gis_tests_.zipcode",
69+
"fields" : {
70+
"code" : "77002",
71+
"poly" : "POLYGON ((-95.365015 29.772327, -95.362415 29.772327, -95.360915 29.771827, -95.354615 29.771827, -95.351515 29.772527, -95.350915 29.765327, -95.351015 29.762436, -95.350115 29.760328, -95.347515 29.758528, -95.352315 29.753928, -95.356415 29.756328, -95.358215 29.754028, -95.360215 29.756328, -95.363415 29.757128, -95.364014 29.75638, -95.363415 29.753928, -95.360015 29.751828, -95.361815 29.749528, -95.362715 29.750028, -95.367516 29.744128, -95.369316 29.745128, -95.373916 29.744128, -95.380116 29.738028, -95.387916 29.727929, -95.388516 29.729629, -95.387916 29.732129, -95.382916 29.737428, -95.376616 29.742228, -95.372616 29.747228, -95.378601 29.750846, -95.378616 29.752028, -95.378616 29.754428, -95.376016 29.754528, -95.374616 29.759828, -95.373616 29.761128, -95.371916 29.763928, -95.372316 29.768727, -95.365884 29.76791, -95.366015 29.767127, -95.358715 29.765327, -95.358615 29.766327, -95.359115 29.767227, -95.360215 29.767027, -95.362783 29.768267, -95.365315 29.770527, -95.365015 29.772327))"
72+
}
73+
},
74+
{
75+
"pk": "000000000000000000000002",
76+
"model": "gis_tests_.zipcode",
77+
"fields" : {
78+
"code" : "77005",
79+
"poly" : "POLYGON ((-95.447918 29.727275, -95.428017 29.728729, -95.421117 29.729029, -95.418617 29.727629, -95.418517 29.726429, -95.402117 29.726629, -95.402117 29.725729, -95.395316 29.725729, -95.391916 29.726229, -95.389716 29.725829, -95.396517 29.715429, -95.397517 29.715929, -95.400917 29.711429, -95.411417 29.715029, -95.418417 29.714729, -95.418317 29.70623, -95.440818 29.70593, -95.445018 29.70683, -95.446618 29.70763, -95.447418 29.71003, -95.447918 29.727275))"
80+
}
81+
},
82+
{
83+
"pk": "000000000000000000000003",
84+
"model": "gis_tests_.zipcode",
85+
"fields" : {
86+
"code" : "77025",
87+
"poly" : "POLYGON ((-95.418317 29.70623, -95.414717 29.706129, -95.414617 29.70533, -95.418217 29.70533, -95.419817 29.69533, -95.419484 29.694196, -95.417166 29.690901, -95.414517 29.69433, -95.413317 29.69263, -95.412617 29.68973, -95.412817 29.68753, -95.414087 29.685055, -95.419165 29.685428, -95.421617 29.68513, -95.425717 29.67983, -95.425017 29.67923, -95.424517 29.67763, -95.427418 29.67763, -95.438018 29.664631, -95.436713 29.664411, -95.440118 29.662231, -95.439218 29.661031, -95.437718 29.660131, -95.435718 29.659731, -95.431818 29.660331, -95.441418 29.656631, -95.441318 29.656331, -95.441818 29.656131, -95.441718 29.659031, -95.441118 29.661031, -95.446718 29.656431, -95.446518 29.673431, -95.446918 29.69013, -95.447418 29.71003, -95.446618 29.70763, -95.445018 29.70683, -95.440818 29.70593, -95.418317 29.70623))"
88+
}
89+
},
90+
{
91+
"pk": "000000000000000000000004",
92+
"model": "gis_tests_.zipcode",
93+
"fields" : {
94+
"code" : "77401",
95+
"poly" : "POLYGON ((-95.447918 29.727275, -95.447418 29.71003, -95.446918 29.69013, -95.454318 29.68893, -95.475819 29.68903, -95.475819 29.69113, -95.484419 29.69103, -95.484519 29.69903, -95.480419 29.70133, -95.480419 29.69833, -95.474119 29.69833, -95.474119 29.70453, -95.472719 29.71283, -95.468019 29.71293, -95.468219 29.720229, -95.464018 29.720229, -95.464118 29.724529, -95.463018 29.725929, -95.459818 29.726129, -95.459918 29.720329, -95.451418 29.720429, -95.451775 29.726303, -95.451318 29.727029, -95.447918 29.727275))"
96+
}
97+
}
98+
]

tests/gis_tests_/models.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,10 @@
22

33

44
class City(models.Model):
5+
name = models.CharField(max_length=30)
56
point = models.PointField()
7+
8+
9+
class Zipcode(models.Model):
10+
code = models.CharField(max_length=10)
11+
poly = models.PolygonField(geography=True)

tests/gis_tests_/tests.py

Lines changed: 67 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,88 @@
11
from django.contrib.gis.geos import Point
2+
from django.contrib.gis.measure import Distance
23
from django.db import NotSupportedError
34
from django.test import TestCase, skipUnlessDBFeature
45

5-
from .models import City
6+
from .models import City, Zipcode
67

78

89
@skipUnlessDBFeature("gis_enabled")
910
class LookupTests(TestCase):
10-
def test_unsupported_lookups(self):
11+
fixtures = ["initial"]
12+
13+
def test_unsupported(self):
1114
msg = "MongoDB does not support the 'same_as' lookup."
1215
with self.assertRaisesMessage(NotSupportedError, msg):
1316
City.objects.get(point__same_as=Point(95, 30))
1417

15-
def test_within_lookup(self):
16-
city = City.objects.create(point=Point(95, 30))
17-
qs = City.objects.filter(point__within=Point(95, 30).buffer(10))
18-
self.assertIn(city, qs)
18+
def test_contains(self):
19+
houston = City.objects.get(name="Houston")
20+
qs = City.objects.filter(point__contains=Point(-95.363151, 29.763374))
21+
self.assertEqual(qs.count(), 1)
22+
self.assertEqual(houston, qs.first())
1923

20-
def test_intersects_lookup(self):
21-
city = City.objects.create(point=Point(95, 30))
22-
qs = City.objects.filter(point__intersects=Point(95, 30).buffer(10))
23-
self.assertIn(city, qs)
24-
25-
def test_disjoint_lookup(self):
26-
city = City.objects.create(point=Point(50, 30))
24+
def test_disjoint(self):
25+
houston = City.objects.get(name="Houston")
2726
qs = City.objects.filter(point__disjoint=Point(100, 50))
28-
self.assertIn(city, qs)
27+
self.assertIn(houston, qs)
2928

30-
def test_contains_lookup(self):
31-
city = City.objects.create(point=Point(95, 30))
32-
qs = City.objects.filter(point__contains=Point(95, 30))
33-
self.assertIn(city, qs)
29+
def test_distance_gt(self):
30+
houston = City.objects.get(name="Houston")
31+
dallas = City.objects.get(name="Dallas") # Roughly ~363 km from Houston
32+
qs = City.objects.filter(point__distance_gt=(houston.point, 362826))
33+
self.assertEqual(qs.count(), 6)
34+
self.assertNotIn(dallas, list(qs))
3435

35-
def test_distance_gt_lookup(self):
36-
city = City.objects.create(point=Point(95, 30))
37-
qs = City.objects.filter(point__distance_gt=(Point(0, 0), 100))
38-
self.assertIn(city, qs)
36+
def test_distance_gte(self):
37+
houston = City.objects.get(name="Houston")
38+
dallas = City.objects.get(name="Dallas") # Roughly ~363 km from Houston
39+
qs = City.objects.filter(point__distance_gte=(houston.point, 362825))
40+
self.assertEqual(qs.count(), 7)
41+
self.assertIn(dallas, list(qs))
3942

40-
def test_distance_lt_lookup(self):
41-
city = City.objects.create(point=Point(40.7589, -73.9851))
42-
qs = City.objects.filter(point__distance_lt=(Point(40.7670, -73.9820), 1000))
43-
self.assertIn(city, qs)
43+
def test_distance_lt(self):
44+
houston = City.objects.get(name="Houston")
45+
qs = City.objects.filter(point__distance_lt=(houston.point, 362825))
46+
self.assertEqual(qs.count(), 1)
47+
self.assertEqual(houston, qs.first())
4448

45-
def test_distance_gte_lookup(self):
46-
city = City.objects.create(point=Point(95, 30))
47-
qs = City.objects.filter(point__distance_gt=(Point(0, 0), 100))
48-
self.assertIn(city, qs)
49+
def test_distance_lte(self):
50+
houston = City.objects.get(name="Houston")
51+
dallas = City.objects.get(name="Dallas") # Roughly ~363 km from Houston
52+
qs = City.objects.filter(point__distance_lte=(houston.point, 362826))
53+
self.assertEqual(qs.count(), 2)
54+
self.assertEqual([houston, dallas], list(qs))
4955

50-
def test_distance_lte_lookup(self):
51-
city = City.objects.create(point=Point(40.7589, -73.9851))
52-
qs = City.objects.filter(point__distance_lt=(Point(40.7670, -73.9820), 1000))
53-
self.assertIn(city, qs)
56+
def test_distance_units(self):
57+
chicago = City.objects.get(name="Chicago")
58+
lawrence = City.objects.get(name="Lawrence")
59+
qs = City.objects.filter(point__distance_lt=(chicago.point, Distance(km=720)))
60+
self.assertEqual(qs.count(), 2)
61+
self.assertEqual([lawrence, chicago], list(qs))
62+
qs = City.objects.filter(point__distance_lt=(chicago.point, Distance(mi=447)))
63+
self.assertEqual(qs.count(), 2)
64+
self.assertEqual([lawrence, chicago], list(qs))
5465

55-
def test_dwithin_lookup(self):
56-
city = City.objects.create(point=Point(40.7589, -73.9851))
57-
qs = City.objects.filter(point__dwithin=(Point(40.7670, -73.9820), 1000))
66+
def test_dwithin(self):
67+
houston = City.objects.get(name="Houston")
68+
qs = City.objects.filter(point__dwithin=(houston.point, 0.2))
69+
self.assertEqual(qs.count(), 5)
70+
71+
def test_dwithin_unsupported_units(self):
72+
qs = City.objects.filter(point__dwithin=(Point(40.7670, -73.9820), Distance(km=1)))
73+
with self.assertRaisesMessage(
74+
ValueError,
75+
"Only numeric values of radian units are allowed on geodetic distance queries.",
76+
):
77+
qs.first()
78+
79+
def test_intersects(self):
80+
city = City.objects.create(point=Point(95, 30))
81+
qs = City.objects.filter(point__intersects=Point(95, 30).buffer(10))
82+
self.assertEqual(qs.count(), 1)
5883
self.assertIn(city, qs)
84+
85+
def test_within(self):
86+
zipcode = Zipcode.objects.get(code="77002")
87+
qs = City.objects.filter(point__within=zipcode.poly).values_list("name", flat=True)
88+
self.assertEqual(["Houston"], list(qs))

0 commit comments

Comments
 (0)