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
This commit is contained in:
Justin Bronn 2008-11-05 17:51:11 +00:00
parent 1515b13d1a
commit b401d44a9f
3 changed files with 43 additions and 20 deletions

View File

@ -605,13 +605,19 @@ class GeoQuerySet(QuerySet):
# set on the `GeoQuery` object of this queryset.
if aggregate: self.query.aggregate = True
# Is this operation going to be on a related geographic field?
if not geo_field in self.model._meta.fields:
opts = self.model._meta
if not geo_field in opts.fields:
# Is this operation going to be on a related geographic field?
# If so, it'll have to be added to the select related information
# (e.g., if 'location__point' was given as the field name).
self.query.add_select_related([field_name])
self.query.pre_sql_setup()
rel_table, rel_col = self.query.related_select_cols[self.query.related_select_fields.index(geo_field)]
return self.query._field_column(geo_field, rel_table)
elif not geo_field in opts.local_fields:
# This geographic field is inherited from another model, so we have to
# use the db table for the _parent_ model instead.
tmp_fld, parent_model, direct, m2m = opts.get_field_by_name(geo_field.name)
return self.query._field_column(geo_field, parent_model._meta.db_table)
else:
return self.query._field_column(geo_field)

View File

@ -16,6 +16,11 @@ class City(models.Model):
objects = models.GeoManager()
def __unicode__(self): return self.name
# This is an inherited model from City
class PennsylvaniaCity(City):
county = models.CharField(max_length=30)
objects = models.GeoManager() # TODO: This should be implicitly inherited.
class State(models.Model):
name = models.CharField(max_length=30)
poly = models.PolygonField(null=null_flag) # Allowing NULL geometries here.

View File

@ -1,10 +1,10 @@
import os, unittest
from models import Country, City, State, Feature, MinusOneSRID
from models import Country, City, PennsylvaniaCity, State, Feature, MinusOneSRID
from django.contrib.gis import gdal
from django.contrib.gis.db.backend import SpatialBackend
from django.contrib.gis.geos import *
from django.contrib.gis.measure import Distance
from django.contrib.gis.tests.utils import no_oracle, no_postgis, oracle, postgis
from django.contrib.gis.tests.utils import no_oracle, no_postgis
# TODO: Some tests depend on the success/failure of previous tests, these should
# be decoupled. This flag is an artifact of this problem, and makes debugging easier;
@ -17,7 +17,7 @@ class GeoModelTest(unittest.TestCase):
def test01_initial_sql(self):
"Testing geographic initial SQL."
if DISABLE: return
if oracle:
if SpatialBackend.oracle:
# Oracle doesn't allow strings longer than 4000 characters
# in SQL files, and I'm stumped on how to use Oracle BFILE's
# in PLSQL, so we set up the larger geometries manually, rather
@ -38,7 +38,7 @@ class GeoModelTest(unittest.TestCase):
self.assertEqual(8, City.objects.count())
# Oracle cannot handle NULL geometry values w/certain queries.
if oracle: n_state = 2
if SpatialBackend.oracle: n_state = 2
else: n_state = 3
self.assertEqual(n_state, State.objects.count())
@ -147,7 +147,7 @@ class GeoModelTest(unittest.TestCase):
ptown1 = City.objects.gml(field_name='point', precision=9).get(name='Pueblo')
ptown2 = City.objects.gml(precision=9).get(name='Pueblo')
if oracle:
if SpatialBackend.oracle:
# No precision parameter for Oracle :-/
import re
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 @@ class GeoModelTest(unittest.TestCase):
# Asserting the result of the transform operation with the values in
# the pre-transformed points. Oracle does not have the 3084 SRID.
if not oracle:
if not SpatialBackend.oracle:
h = City.objects.transform(htown.srid).get(name='Houston')
self.assertEqual(3084, h.point.srid)
self.assertAlmostEqual(htown.x, h.point.x, prec)
@ -214,7 +214,7 @@ class GeoModelTest(unittest.TestCase):
qs1 = City.objects.filter(point__disjoint=ptown.point)
self.assertEqual(7, qs1.count())
if not postgis:
if not SpatialBackend.postgis:
# TODO: Do NULL columns bork queries on PostGIS? The following
# error is encountered:
# psycopg2.ProgrammingError: invalid memory alloc request size 4294957297
@ -231,7 +231,7 @@ class GeoModelTest(unittest.TestCase):
# Seeing what cities are in Texas, should get Houston and Dallas,
# and Oklahoma City because 'contained' only checks on the
# _bounding box_ of the Geometries.
if not oracle:
if not SpatialBackend.oracle:
qs = City.objects.filter(point__contained=texas.mpoly)
self.assertEqual(3, qs.count())
cities = ['Houston', 'Dallas', 'Oklahoma City']
@ -259,7 +259,7 @@ class GeoModelTest(unittest.TestCase):
self.assertEqual(0, len(Country.objects.filter(mpoly__contains=okcity.point.wkt))) # Qeury w/WKT
# OK City is contained w/in bounding box of Texas.
if not oracle:
if not SpatialBackend.oracle:
qs = Country.objects.filter(mpoly__bbcontains=okcity.point)
self.assertEqual(1, len(qs))
self.assertEqual('Texas', qs[0].name)
@ -272,7 +272,7 @@ class GeoModelTest(unittest.TestCase):
wgs_pnt = fromstr(sa_4326, srid=4326) # Our reference point in WGS84
# Oracle doesn't have SRID 3084, using 41157.
if oracle:
if SpatialBackend.oracle:
# San Antonio in 'Texas 4205, Southern Zone (1983, meters)' (SRID 41157)
# Used the following Oracle SQL to get this value:
# SELECT SDO_UTIL.TO_WKTGEOMETRY(SDO_CS.TRANSFORM(SDO_GEOMETRY('POINT (-98.493183 29.424170)', 4326), 41157)) FROM DUAL;
@ -287,7 +287,7 @@ class GeoModelTest(unittest.TestCase):
# `SDO_OVERLAPBDYINTERSECT` operates differently from
# `ST_Intersects`, so contains is used instead.
nad_pnt = fromstr(nad_wkt, srid=nad_srid)
if oracle:
if SpatialBackend.oracle:
tx = Country.objects.get(mpoly__contains=nad_pnt)
else:
tx = Country.objects.get(mpoly__intersects=nad_pnt)
@ -329,7 +329,7 @@ class GeoModelTest(unittest.TestCase):
self.assertEqual(True, 'Kansas' in state_names)
# Saving another commonwealth w/a NULL geometry.
if not oracle:
if not SpatialBackend.oracle:
# TODO: Fix saving w/NULL geometry on Oracle.
State(name='Northern Mariana Islands', poly=None).save()
@ -398,11 +398,11 @@ class GeoModelTest(unittest.TestCase):
self.assertRaises(e, qs.count)
# Relate works differently for the different backends.
if postgis:
if SpatialBackend.postgis:
contains_mask = 'T*T***FF*'
within_mask = 'T*F**F***'
intersects_mask = 'T********'
elif oracle:
elif SpatialBackend.oracle:
contains_mask = 'contains'
within_mask = 'inside'
# TODO: This is not quite the same as the PostGIS mask above
@ -417,7 +417,7 @@ class GeoModelTest(unittest.TestCase):
self.assertEqual('Lawrence', City.objects.get(point__relate=(ks.poly, within_mask)).name)
# Testing intersection relation mask.
if not oracle:
if not SpatialBackend.oracle:
self.assertEqual('Texas', Country.objects.get(mpoly__relate=(pnt1, intersects_mask)).name)
self.assertEqual('Texas', Country.objects.get(mpoly__relate=(pnt2, intersects_mask)).name)
self.assertEqual('Lawrence', City.objects.get(point__relate=(ks.poly, intersects_mask)).name)
@ -479,7 +479,7 @@ class GeoModelTest(unittest.TestCase):
"Testing the `centroid` GeoQuerySet method."
if DISABLE: return
qs = State.objects.exclude(poly__isnull=True).centroid()
if oracle: tol = 0.1
if SpatialBackend.oracle: tol = 0.1
else: tol = 0.000000001
for s in qs:
self.assertEqual(True, s.poly.centroid.equals_exact(s.centroid, tol))
@ -536,14 +536,14 @@ class GeoModelTest(unittest.TestCase):
for c in City.objects.filter(point__isnull=False).num_geom():
# Oracle will return 1 for the number of geometries on non-collections,
# whereas PostGIS will return None.
if postgis: self.assertEqual(None, c.num_geom)
if SpatialBackend.postgis: self.assertEqual(None, c.num_geom)
else: self.assertEqual(1, c.num_geom)
def test24_numpoints(self):
"Testing the `num_points` GeoQuerySet method."
if DISABLE: return
for c in Country.objects.num_points(): self.assertEqual(c.mpoly.num_points, c.num_points)
if postgis:
if SpatialBackend.postgis:
# Oracle cannot count vertices in Point geometries.
for c in City.objects.num_points(): self.assertEqual(1, c.num_points)
@ -558,6 +558,18 @@ class GeoModelTest(unittest.TestCase):
self.assertEqual(c.mpoly.sym_difference(geom), c.sym_difference)
self.assertEqual(c.mpoly.union(geom), c.union)
def test26_inherited_geofields(self):
"Test GeoQuerySet methods on inherited Geometry fields."
# Creating a Pennsylvanian city.
mansfield = PennsylvaniaCity.objects.create(name='Mansfield', county='Tioga', point='POINT(-77.071445 41.823881)')
# All transformation SQL will need to be performed on the
# _parent_ table.
qs = PennsylvaniaCity.objects.transform(32128)
self.assertEqual(1, qs.count())
for pc in qs: self.assertEqual(32128, pc.point.srid)
from test_feeds import GeoFeedTest
from test_sitemaps import GeoSitemapTest
def suite():