Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #9364 -- now uses the appropriate database table for inherited …

…`GeometryField`s; now uses the `SpatialBackend` booleans in tests.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@9336 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit b401d44a9f51161f3b42ebc3f70f8c1fd0b5b782 1 parent 1515b13
Justin Bronn authored November 05, 2008
10  django/contrib/gis/db/models/query.py
@@ -605,13 +605,19 @@ def _geocol_select(self, geo_field, field_name, aggregate=False):
605 605
         # set on the `GeoQuery` object of this queryset.
606 606
         if aggregate: self.query.aggregate = True
607 607
 
608  
-        # Is this operation going to be on a related geographic field?
609  
-        if not geo_field in self.model._meta.fields:
  608
+        opts = self.model._meta
  609
+        if not geo_field in opts.fields:
  610
+            # Is this operation going to be on a related geographic field?
610 611
             # If so, it'll have to be added to the select related information
611 612
             # (e.g., if 'location__point' was given as the field name).
612 613
             self.query.add_select_related([field_name])
613 614
             self.query.pre_sql_setup()
614 615
             rel_table, rel_col = self.query.related_select_cols[self.query.related_select_fields.index(geo_field)]
615 616
             return self.query._field_column(geo_field, rel_table)
  617
+        elif not geo_field in opts.local_fields:
  618
+            # This geographic field is inherited from another model, so we have to
  619
+            # use the db table for the _parent_ model instead.
  620
+            tmp_fld, parent_model, direct, m2m = opts.get_field_by_name(geo_field.name)
  621
+            return self.query._field_column(geo_field, parent_model._meta.db_table)
616 622
         else:
617 623
             return self.query._field_column(geo_field)
5  django/contrib/gis/tests/geoapp/models.py
@@ -16,6 +16,11 @@ class City(models.Model):
16 16
     objects = models.GeoManager()
17 17
     def __unicode__(self): return self.name
18 18
 
  19
+# This is an inherited model from City
  20
+class PennsylvaniaCity(City):
  21
+    county = models.CharField(max_length=30)
  22
+    objects = models.GeoManager() # TODO: This should be implicitly inherited.
  23
+
19 24
 class State(models.Model):
20 25
     name = models.CharField(max_length=30)
21 26
     poly = models.PolygonField(null=null_flag) # Allowing NULL geometries here.
48  django/contrib/gis/tests/geoapp/tests.py
... ...
@@ -1,10 +1,10 @@
1 1
 import os, unittest
2  
-from models import Country, City, State, Feature, MinusOneSRID
  2
+from models import Country, City, PennsylvaniaCity, State, Feature, MinusOneSRID
3 3
 from django.contrib.gis import gdal
4 4
 from django.contrib.gis.db.backend import SpatialBackend
5 5
 from django.contrib.gis.geos import *
6 6
 from django.contrib.gis.measure import Distance
7  
-from django.contrib.gis.tests.utils import no_oracle, no_postgis, oracle, postgis
  7
+from django.contrib.gis.tests.utils import no_oracle, no_postgis
8 8
 
9 9
 # TODO: Some tests depend on the success/failure of previous tests, these should
10 10
 # be decoupled.  This flag is an artifact of this problem, and makes debugging easier;
@@ -17,7 +17,7 @@ class GeoModelTest(unittest.TestCase):
17 17
     def test01_initial_sql(self):
18 18
         "Testing geographic initial SQL."
19 19
         if DISABLE: return
20  
-        if oracle:
  20
+        if SpatialBackend.oracle:
21 21
             # Oracle doesn't allow strings longer than 4000 characters
22 22
             # in SQL files, and I'm stumped on how to use Oracle BFILE's
23 23
             # in PLSQL, so we set up the larger geometries manually, rather
@@ -38,7 +38,7 @@ def get_file(wkt_file):
38 38
         self.assertEqual(8, City.objects.count())
39 39
 
40 40
         # Oracle cannot handle NULL geometry values w/certain queries.
41  
-        if oracle: n_state = 2
  41
+        if SpatialBackend.oracle: n_state = 2
42 42
         else: n_state = 3
43 43
         self.assertEqual(n_state, State.objects.count())
44 44
 
@@ -147,7 +147,7 @@ def test03b_gml(self):
147 147
         ptown1 = City.objects.gml(field_name='point', precision=9).get(name='Pueblo')
148 148
         ptown2 = City.objects.gml(precision=9).get(name='Pueblo')
149 149
 
150  
-        if oracle:
  150
+        if SpatialBackend.oracle:
151 151
             # No precision parameter for Oracle :-/
152 152
             import re
153 153
             gml_regex = re.compile(r'<gml:Point srsName="SDO:4326" xmlns:gml="http://www.opengis.net/gml"><gml:coordinates decimal="\." cs="," ts=" ">-104.60925199\d+,38.25500\d+ </gml:coordinates></gml:Point>')
@@ -167,7 +167,7 @@ def test04_transform(self):
167 167
 
168 168
         # Asserting the result of the transform operation with the values in
169 169
         #  the pre-transformed points.  Oracle does not have the 3084 SRID.
170  
-        if not oracle:
  170
+        if not SpatialBackend.oracle:
171 171
             h = City.objects.transform(htown.srid).get(name='Houston')
172 172
             self.assertEqual(3084, h.point.srid)
173 173
             self.assertAlmostEqual(htown.x, h.point.x, prec)
@@ -214,7 +214,7 @@ def test09_disjoint(self):
214 214
         qs1 = City.objects.filter(point__disjoint=ptown.point)
215 215
         self.assertEqual(7, qs1.count())
216 216
 
217  
-        if not postgis:
  217
+        if not SpatialBackend.postgis:
218 218
             # TODO: Do NULL columns bork queries on PostGIS?  The following
219 219
             # error is encountered:
220 220
             #  psycopg2.ProgrammingError: invalid memory alloc request size 4294957297
@@ -231,7 +231,7 @@ def test10_contains_contained(self):
231 231
         # Seeing what cities are in Texas, should get Houston and Dallas,
232 232
         #  and Oklahoma City because 'contained' only checks on the
233 233
         #  _bounding box_ of the Geometries.
234  
-        if not oracle:
  234
+        if not SpatialBackend.oracle:
235 235
             qs = City.objects.filter(point__contained=texas.mpoly)
236 236
             self.assertEqual(3, qs.count())
237 237
             cities = ['Houston', 'Dallas', 'Oklahoma City']
@@ -259,7 +259,7 @@ def test10_contains_contained(self):
259 259
         self.assertEqual(0, len(Country.objects.filter(mpoly__contains=okcity.point.wkt))) # Qeury w/WKT
260 260
 
261 261
         # OK City is contained w/in bounding box of Texas.
262  
-        if not oracle:
  262
+        if not SpatialBackend.oracle:
263 263
             qs = Country.objects.filter(mpoly__bbcontains=okcity.point)
264 264
             self.assertEqual(1, len(qs))
265 265
             self.assertEqual('Texas', qs[0].name)
@@ -272,7 +272,7 @@ def test11_lookup_insert_transform(self):
272 272
         wgs_pnt = fromstr(sa_4326, srid=4326) # Our reference point in WGS84
273 273
 
274 274
         # Oracle doesn't have SRID 3084, using 41157.
275  
-        if oracle:
  275
+        if SpatialBackend.oracle:
276 276
             # San Antonio in 'Texas 4205, Southern Zone (1983, meters)' (SRID 41157)
277 277
             # Used the following Oracle SQL to get this value:
278 278
             #  SELECT SDO_UTIL.TO_WKTGEOMETRY(SDO_CS.TRANSFORM(SDO_GEOMETRY('POINT (-98.493183 29.424170)', 4326), 41157)) FROM DUAL;
@@ -287,7 +287,7 @@ def test11_lookup_insert_transform(self):
287 287
         # `SDO_OVERLAPBDYINTERSECT` operates differently from
288 288
         # `ST_Intersects`, so contains is used instead.
289 289
         nad_pnt = fromstr(nad_wkt, srid=nad_srid)
290  
-        if oracle:
  290
+        if SpatialBackend.oracle:
291 291
             tx = Country.objects.get(mpoly__contains=nad_pnt) 
292 292
         else:
293 293
             tx = Country.objects.get(mpoly__intersects=nad_pnt)
@@ -329,7 +329,7 @@ def test12_null_geometries(self):
329 329
         self.assertEqual(True, 'Kansas' in state_names)
330 330
 
331 331
         # Saving another commonwealth w/a NULL geometry.
332  
-        if not oracle:
  332
+        if not SpatialBackend.oracle:
333 333
             # TODO: Fix saving w/NULL geometry on Oracle.
334 334
             State(name='Northern Mariana Islands', poly=None).save()
335 335
 
@@ -398,11 +398,11 @@ def test15_relate(self):
398 398
             self.assertRaises(e, qs.count)
399 399
 
400 400
         # Relate works differently for the different backends.
401  
-        if postgis:
  401
+        if SpatialBackend.postgis:
402 402
             contains_mask = 'T*T***FF*'
403 403
             within_mask = 'T*F**F***'
404 404
             intersects_mask = 'T********'
405  
-        elif oracle:
  405
+        elif SpatialBackend.oracle:
406 406
             contains_mask = 'contains'
407 407
             within_mask = 'inside'
408 408
             # TODO: This is not quite the same as the PostGIS mask above
@@ -417,7 +417,7 @@ def test15_relate(self):
417 417
         self.assertEqual('Lawrence', City.objects.get(point__relate=(ks.poly, within_mask)).name)
418 418
 
419 419
         # Testing intersection relation mask.
420  
-        if not oracle:
  420
+        if not SpatialBackend.oracle:
421 421
             self.assertEqual('Texas', Country.objects.get(mpoly__relate=(pnt1, intersects_mask)).name)
422 422
             self.assertEqual('Texas', Country.objects.get(mpoly__relate=(pnt2, intersects_mask)).name)
423 423
             self.assertEqual('Lawrence', City.objects.get(point__relate=(ks.poly, intersects_mask)).name)
@@ -479,7 +479,7 @@ def test19_centroid(self):
479 479
         "Testing the `centroid` GeoQuerySet method."
480 480
         if DISABLE: return
481 481
         qs = State.objects.exclude(poly__isnull=True).centroid()
482  
-        if oracle: tol = 0.1
  482
+        if SpatialBackend.oracle: tol = 0.1
483 483
         else: tol = 0.000000001
484 484
         for s in qs:
485 485
             self.assertEqual(True, s.poly.centroid.equals_exact(s.centroid, tol))
@@ -536,14 +536,14 @@ def test23_numgeom(self):
536 536
         for c in City.objects.filter(point__isnull=False).num_geom(): 
537 537
             # Oracle will return 1 for the number of geometries on non-collections,
538 538
             # whereas PostGIS will return None.
539  
-            if postgis: self.assertEqual(None, c.num_geom)
  539
+            if SpatialBackend.postgis: self.assertEqual(None, c.num_geom)
540 540
             else: self.assertEqual(1, c.num_geom)
541 541
 
542 542
     def test24_numpoints(self):
543 543
         "Testing the `num_points` GeoQuerySet method."
544 544
         if DISABLE: return
545 545
         for c in Country.objects.num_points(): self.assertEqual(c.mpoly.num_points, c.num_points)
546  
-        if postgis:
  546
+        if SpatialBackend.postgis:
547 547
             # Oracle cannot count vertices in Point geometries.
548 548
             for c in City.objects.num_points(): self.assertEqual(1, c.num_points)
549 549
 
@@ -558,6 +558,18 @@ def test25_geoset(self):
558 558
             self.assertEqual(c.mpoly.sym_difference(geom), c.sym_difference)
559 559
             self.assertEqual(c.mpoly.union(geom), c.union)
560 560
 
  561
+    def test26_inherited_geofields(self):
  562
+        "Test GeoQuerySet methods on inherited Geometry fields."
  563
+        # Creating a Pennsylvanian city.
  564
+        mansfield = PennsylvaniaCity.objects.create(name='Mansfield', county='Tioga', point='POINT(-77.071445 41.823881)')
  565
+
  566
+        # All transformation SQL will need to be performed on the
  567
+        # _parent_ table.
  568
+        qs = PennsylvaniaCity.objects.transform(32128)
  569
+        
  570
+        self.assertEqual(1, qs.count())
  571
+        for pc in qs: self.assertEqual(32128, pc.point.srid)
  572
+
561 573
 from test_feeds import GeoFeedTest
562 574
 from test_sitemaps import GeoSitemapTest
563 575
 def suite():

0 notes on commit b401d44

Please sign in to comment.
Something went wrong with that request. Please try again.