1- from django .contrib .gis .geos import Point
1+ from django .contrib .gis .geos import LineString , Point , Polygon
22from django .contrib .gis .measure import Distance
33from django .db import NotSupportedError
4+ from django .db .models import Case , CharField , Value , When
45from django .test import TestCase , skipUnlessDBFeature
56
67from .models import City , Zipcode
1011class LookupTests (TestCase ):
1112 fixtures = ["initial" ]
1213
13- def test_unsupported (self ):
14- msg = "MongoDB does not support the 'same_as' lookup."
15- with self .assertRaisesMessage (NotSupportedError , msg ):
16- City .objects .get (point__same_as = Point (95 , 30 ))
17-
1814 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 .assertCountEqual (qs , [houston ])
15+ qs = City .objects .filter (point__contains = Point (- 95.363151 , 29.763374 )).values_list (
16+ "name" , flat = True
17+ )
18+ self .assertCountEqual (qs , ["Houston" ])
19+
20+ def test_contains_errors_on_non_point (self ):
21+ qs = City .objects .filter (point__contains = LineString ((0 , 0 ), (1 , 1 )))
22+ message = "MongoDB does not support contains on non-Point query geometries."
23+ with self .assertRaisesMessage (NotSupportedError , message ):
24+ qs .first ()
2225
2326 def test_disjoint (self ):
24- houston = City .objects .get (name = "Houston" )
25- qs = City .objects .filter (point__disjoint = Point (100 , 50 ))
26- self .assertIn (houston , qs )
27+ qs = City .objects .filter (point__disjoint = Point (100 , 50 )).values_list ("name" , flat = True )
28+ self .assertIn ("Houston" , qs )
2729
2830 def test_distance_gt (self ):
2931 houston = City .objects .get (name = "Houston" )
30- dallas = City .objects .get (name = "Dallas" ) # Roughly ~363 km from Houston
31- qs = City .objects .filter (point__distance_gt = (houston .point , 362826 ))
32- self .assertEqual (qs .count (), 6 )
33- self .assertNotIn (dallas , list (qs ))
32+ expected = ["Oklahoma City" , "Wellington" , "Pueblo" , "Lawrence" , "Chicago" , "Victoria" ]
33+ qs = City .objects .filter (point__distance_gt = (houston .point , 362826 )).values_list (
34+ "name" , flat = True
35+ )
36+ self .assertCountEqual (qs , expected )
3437
3538 def test_distance_gte (self ):
3639 houston = City .objects .get (name = "Houston" )
37- dallas = City .objects .get (name = "Dallas" ) # Roughly ~363 km from Houston
38- qs = City .objects .filter (point__distance_gte = (houston .point , 362825 ))
39- self .assertEqual (qs .count (), 7 )
40- self .assertIn (dallas , list (qs ))
40+ expected = [
41+ "Dallas" ,
42+ "Oklahoma City" ,
43+ "Wellington" ,
44+ "Pueblo" ,
45+ "Lawrence" ,
46+ "Chicago" ,
47+ "Victoria" ,
48+ ]
49+ qs = City .objects .filter (point__distance_gte = (houston .point , 362825 )).values_list (
50+ "name" , flat = True
51+ )
52+ self .assertCountEqual (qs , expected )
4153
4254 def test_distance_lt (self ):
4355 houston = City .objects .get (name = "Houston" )
@@ -46,22 +58,27 @@ def test_distance_lt(self):
4658
4759 def test_distance_lte (self ):
4860 houston = City .objects .get (name = "Houston" )
49- dallas = City .objects .get (name = "Dallas" ) # Roughly ~363 km from Houston
50- qs = City .objects .filter (point__distance_lte = (houston .point , 362826 ))
51- self .assertCountEqual (list (qs ), [houston , dallas ])
61+ qs = City .objects .filter (point__distance_lte = (houston .point , 362826 )).values_list (
62+ "name" , flat = True
63+ )
64+ self .assertCountEqual (qs , ["Houston" , "Dallas" ]) # Dallas is roughly ~363 km from Houston
5265
5366 def test_distance_units (self ):
5467 chicago = City .objects .get (name = "Chicago" )
55- lawrence = City .objects .get (name = "Lawrence" )
56- qs = City .objects .filter (point__distance_lt = (chicago .point , Distance (km = 720 )))
57- self .assertCountEqual (list (qs ), [lawrence , chicago ])
58- qs = City .objects .filter (point__distance_lt = (chicago .point , Distance (mi = 447 )))
59- self .assertCountEqual (list (qs ), [lawrence , chicago ])
68+ qs = City .objects .filter (point__distance_lt = (chicago .point , Distance (km = 720 ))).values_list (
69+ "name" , flat = True
70+ )
71+ self .assertCountEqual (qs , ["Lawrence" , "Chicago" ])
72+ qs = City .objects .filter (point__distance_lt = (chicago .point , Distance (mi = 447 ))).values_list (
73+ "name" , flat = True
74+ )
75+ self .assertCountEqual (qs , ["Lawrence" , "Chicago" ])
6076
6177 def test_dwithin (self ):
6278 houston = City .objects .get (name = "Houston" )
63- qs = City .objects .filter (point__dwithin = (houston .point , 0.2 ))
64- self .assertEqual (qs .count (), 5 )
79+ expected = ["Houston" , "Dallas" , "Pueblo" , "Oklahoma City" , "Lawrence" ]
80+ qs = City .objects .filter (point__dwithin = (houston .point , 0.2 )).values_list ("name" , flat = True )
81+ self .assertCountEqual (qs , expected )
6582
6683 def test_dwithin_unsupported_units (self ):
6784 qs = City .objects .filter (point__dwithin = (Point (40.7670 , - 73.9820 ), Distance (km = 1 )))
@@ -72,10 +89,37 @@ def test_dwithin_unsupported_units(self):
7289 def test_intersects (self ):
7390 city = City .objects .create (point = Point (95 , 30 ))
7491 qs = City .objects .filter (point__intersects = Point (95 , 30 ).buffer (10 ))
75- self .assertEqual (qs .count (), 1 )
76- self .assertIn (city , qs )
92+ self .assertCountEqual (qs , [city ])
7793
7894 def test_within (self ):
7995 zipcode = Zipcode .objects .get (code = "77002" )
8096 qs = City .objects .filter (point__within = zipcode .poly ).values_list ("name" , flat = True )
81- self .assertEqual (list (qs ), ["Houston" ])
97+ self .assertCountEqual (qs , ["Houston" ])
98+
99+ def test_unsupported (self ):
100+ msg = "MongoDB does not support the 'same_as' lookup."
101+ with self .assertRaisesMessage (NotSupportedError , msg ):
102+ City .objects .get (point__same_as = Point (95 , 30 ))
103+
104+ def test_unsupported_expr (self ):
105+ downtown_area = Polygon (
106+ (
107+ (- 122.4194 , 37.7749 ),
108+ (- 122.4194 , 37.8049 ),
109+ (- 122.3894 , 37.8049 ),
110+ (- 122.3894 , 37.7749 ),
111+ (- 122.4194 , 37.7749 ),
112+ )
113+ )
114+
115+ qs = City .objects .annotate (
116+ area_type = Case (
117+ When (point__within = downtown_area , then = Value ("Downtown" )),
118+ default = Value ("Other" ),
119+ output_field = CharField (),
120+ )
121+ )
122+
123+ message = "MongoDB does not support GIS lookups as expressions."
124+ with self .assertRaisesMessage (NotSupportedError , message ):
125+ qs .first ()
0 commit comments