1 import os, unittest |
1 import os, unittest |
2 from django.contrib.gis.geos import * |
2 from django.contrib.gis.geos import * |
3 from django.contrib.gis.db.backend import SpatialBackend |
|
4 from django.contrib.gis.db.models import Collect, Count, Extent, F, Union |
3 from django.contrib.gis.db.models import Collect, Count, Extent, F, Union |
5 from django.contrib.gis.tests.utils import no_mysql, no_oracle, no_spatialite |
4 from django.contrib.gis.geometry.backend import Geometry |
|
5 from django.contrib.gis.tests.utils import mysql, oracle, postgis, spatialite, no_mysql, no_oracle, no_spatialite |
6 from django.conf import settings |
6 from django.conf import settings |
7 from models import City, Location, DirectoryEntry, Parcel, Book, Author |
7 from models import City, Location, DirectoryEntry, Parcel, Book, Author |
8 |
8 |
9 cities = (('Aurora', 'TX', -97.516111, 33.058333), |
9 cities = (('Aurora', 'TX', -97.516111, 33.058333), |
10 ('Roswell', 'NM', -104.528056, 33.387222), |
10 ('Roswell', 'NM', -104.528056, 33.387222), |
17 "Setting up for related model tests." |
17 "Setting up for related model tests." |
18 for name, state, lon, lat in cities: |
18 for name, state, lon, lat in cities: |
19 loc = Location.objects.create(point=Point(lon, lat)) |
19 loc = Location.objects.create(point=Point(lon, lat)) |
20 c = City.objects.create(name=name, state=state, location=loc) |
20 c = City.objects.create(name=name, state=state, location=loc) |
21 |
21 |
22 @no_oracle # TODO: Fix select_related() problems w/Oracle and pagination. |
|
23 def test02_select_related(self): |
22 def test02_select_related(self): |
24 "Testing `select_related` on geographic models (see #7126)." |
23 "Testing `select_related` on geographic models (see #7126)." |
25 qs1 = City.objects.all() |
24 qs1 = City.objects.all() |
26 qs2 = City.objects.select_related() |
25 qs2 = City.objects.select_related() |
27 qs3 = City.objects.select_related('location') |
26 qs3 = City.objects.select_related('location') |
32 self.assertEqual(nm, c.name) |
31 self.assertEqual(nm, c.name) |
33 self.assertEqual(st, c.state) |
32 self.assertEqual(st, c.state) |
34 self.assertEqual(Point(lon, lat), c.location.point) |
33 self.assertEqual(Point(lon, lat), c.location.point) |
35 |
34 |
36 @no_mysql |
35 @no_mysql |
37 @no_oracle # Pagination problem is implicated in this test as well. |
|
38 def test03_transform_related(self): |
36 def test03_transform_related(self): |
39 "Testing the `transform` GeoQuerySet method on related geographic models." |
37 "Testing the `transform` GeoQuerySet method on related geographic models." |
40 # All the transformations are to state plane coordinate systems using |
38 # All the transformations are to state plane coordinate systems using |
41 # US Survey Feet (thus a tolerance of 0 implies error w/in 1 survey foot). |
39 # US Survey Feet (thus a tolerance of 0 implies error w/in 1 survey foot). |
42 tol = 0 |
40 tol = 0 |
93 # Creating the reference union geometry depending on the spatial backend, |
91 # Creating the reference union geometry depending on the spatial backend, |
94 # as Oracle will have a different internal ordering of the component |
92 # as Oracle will have a different internal ordering of the component |
95 # geometries than PostGIS. The second union aggregate is for a union |
93 # geometries than PostGIS. The second union aggregate is for a union |
96 # query that includes limiting information in the WHERE clause (in other |
94 # query that includes limiting information in the WHERE clause (in other |
97 # words a `.filter()` precedes the call to `.unionagg()`). |
95 # words a `.filter()` precedes the call to `.unionagg()`). |
98 if SpatialBackend.oracle: |
96 if oracle: |
99 ref_u1 = MultiPoint(p3, p1, p2, srid=4326) |
97 ref_u1 = MultiPoint(p3, p1, p2, srid=4326) |
100 ref_u2 = MultiPoint(p3, p2, srid=4326) |
98 ref_u2 = MultiPoint(p3, p2, srid=4326) |
101 else: |
99 else: |
102 ref_u1 = MultiPoint(p1, p2, p3, srid=4326) |
100 ref_u1 = MultiPoint(p1, p2, p3, srid=4326) |
103 ref_u2 = MultiPoint(p2, p3, srid=4326) |
101 ref_u2 = MultiPoint(p2, p3, srid=4326) |
142 # border. |
140 # border. |
143 qs = Parcel.objects.filter(center1__within=F('border1')) |
141 qs = Parcel.objects.filter(center1__within=F('border1')) |
144 self.assertEqual(1, len(qs)) |
142 self.assertEqual(1, len(qs)) |
145 self.assertEqual('P2', qs[0].name) |
143 self.assertEqual('P2', qs[0].name) |
146 |
144 |
147 if not SpatialBackend.mysql: |
145 if not mysql: |
148 # This time center2 is in a different coordinate system and needs |
146 # This time center2 is in a different coordinate system and needs |
149 # to be wrapped in transformation SQL. |
147 # to be wrapped in transformation SQL. |
150 qs = Parcel.objects.filter(center2__within=F('border1')) |
148 qs = Parcel.objects.filter(center2__within=F('border1')) |
151 self.assertEqual(1, len(qs)) |
149 self.assertEqual(1, len(qs)) |
152 self.assertEqual('P2', qs[0].name) |
150 self.assertEqual('P2', qs[0].name) |
155 # to the point in the City ForeignKey. |
153 # to the point in the City ForeignKey. |
156 qs = Parcel.objects.filter(center1=F('city__location__point')) |
154 qs = Parcel.objects.filter(center1=F('city__location__point')) |
157 self.assertEqual(1, len(qs)) |
155 self.assertEqual(1, len(qs)) |
158 self.assertEqual('P1', qs[0].name) |
156 self.assertEqual('P1', qs[0].name) |
159 |
157 |
160 if not SpatialBackend.mysql: |
158 if not mysql: |
161 # This time the city column should be wrapped in transformation SQL. |
159 # This time the city column should be wrapped in transformation SQL. |
162 qs = Parcel.objects.filter(border2__contains=F('city__location__point')) |
160 qs = Parcel.objects.filter(border2__contains=F('city__location__point')) |
163 self.assertEqual(1, len(qs)) |
161 self.assertEqual(1, len(qs)) |
164 self.assertEqual('P1', qs[0].name) |
162 self.assertEqual('P1', qs[0].name) |
165 |
163 |
173 # Incrementing through each of the models, dictionaries, and tuples |
171 # Incrementing through each of the models, dictionaries, and tuples |
174 # returned by the different types of GeoQuerySets. |
172 # returned by the different types of GeoQuerySets. |
175 for m, d, t in zip(gqs, gvqs, gvlqs): |
173 for m, d, t in zip(gqs, gvqs, gvlqs): |
176 # The values should be Geometry objects and not raw strings returned |
174 # The values should be Geometry objects and not raw strings returned |
177 # by the spatial database. |
175 # by the spatial database. |
178 self.failUnless(isinstance(d['point'], SpatialBackend.Geometry)) |
176 self.failUnless(isinstance(d['point'], Geometry)) |
179 self.failUnless(isinstance(t[1], SpatialBackend.Geometry)) |
177 self.failUnless(isinstance(t[1], Geometry)) |
180 self.assertEqual(m.point, d['point']) |
178 self.assertEqual(m.point, d['point']) |
181 self.assertEqual(m.point, t[1]) |
179 self.assertEqual(m.point, t[1]) |
182 |
180 |
183 def test08_defer_only(self): |
181 def test08_defer_only(self): |
184 "Testing defer() and only() on Geographic models." |
182 "Testing defer() and only() on Geographic models." |
236 "Testing `Count` aggregate use with the `GeoManager` on geo-fields." |
234 "Testing `Count` aggregate use with the `GeoManager` on geo-fields." |
237 # Creating a new City, 'Fort Worth', that uses the same location |
235 # Creating a new City, 'Fort Worth', that uses the same location |
238 # as Dallas. |
236 # as Dallas. |
239 dallas = City.objects.get(name='Dallas') |
237 dallas = City.objects.get(name='Dallas') |
240 ftworth = City.objects.create(name='Fort Worth', state='TX', location=dallas.location) |
238 ftworth = City.objects.create(name='Fort Worth', state='TX', location=dallas.location) |
241 |
239 |
242 # Count annotation should be 2 for the Dallas location now. |
240 # Count annotation should be 2 for the Dallas location now. |
243 loc = Location.objects.annotate(num_cities=Count('city')).get(id=dallas.location.id) |
241 loc = Location.objects.annotate(num_cities=Count('city')).get(id=dallas.location.id) |
244 self.assertEqual(2, loc.num_cities) |
242 self.assertEqual(2, loc.num_cities) |
245 |
243 |
246 def test12b_count(self): |
244 def test12b_count(self): |
277 @no_oracle |
275 @no_oracle |
278 @no_spatialite |
276 @no_spatialite |
279 def test14_collect(self): |
277 def test14_collect(self): |
280 "Testing the `collect` GeoQuerySet method and `Collect` aggregate." |
278 "Testing the `collect` GeoQuerySet method and `Collect` aggregate." |
281 # Reference query: |
279 # Reference query: |
282 # SELECT AsText(ST_Collect("relatedapp_location"."point")) FROM "relatedapp_city" LEFT OUTER JOIN |
280 # SELECT AsText(ST_Collect("relatedapp_location"."point")) FROM "relatedapp_city" LEFT OUTER JOIN |
283 # "relatedapp_location" ON ("relatedapp_city"."location_id" = "relatedapp_location"."id") |
281 # "relatedapp_location" ON ("relatedapp_city"."location_id" = "relatedapp_location"."id") |
284 # WHERE "relatedapp_city"."state" = 'TX'; |
282 # WHERE "relatedapp_city"."state" = 'TX'; |
285 ref_geom = fromstr('MULTIPOINT(-97.516111 33.058333,-96.801611 32.782057,-95.363151 29.763374,-96.801611 32.782057)') |
283 ref_geom = fromstr('MULTIPOINT(-97.516111 33.058333,-96.801611 32.782057,-95.363151 29.763374,-96.801611 32.782057)') |
286 |
284 |
287 c1 = City.objects.filter(state='TX').collect(field_name='location__point') |
285 c1 = City.objects.filter(state='TX').collect(field_name='location__point') |
288 c2 = City.objects.filter(state='TX').aggregate(Collect('location__point'))['location__point__collect'] |
286 c2 = City.objects.filter(state='TX').aggregate(Collect('location__point'))['location__point__collect'] |
289 |
287 |
290 for coll in (c1, c2): |
288 for coll in (c1, c2): |
291 # Even though Dallas and Ft. Worth share same point, Collect doesn't |
289 # Even though Dallas and Ft. Worth share same point, Collect doesn't |