From be89c9ababd85ec25606b39b408a2ab7ee6da357 Mon Sep 17 00:00:00 2001 From: Justin Bronn Date: Mon, 2 Nov 2009 02:17:56 +0000 Subject: [PATCH] Fixed #12093 -- `LayerMapping` now takes into account model inheritance when looking for the geometry column; forgot to diable extent regression test on MySQL. git-svn-id: http://code.djangoproject.com/svn/django/trunk@11703 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- .../contrib/gis/tests/geoapp/test_regress.py | 1 + django/contrib/gis/tests/layermap/models.py | 14 ++++++++++++ django/contrib/gis/tests/layermap/tests.py | 22 ++++++++++++++++++- django/contrib/gis/utils/layermapping.py | 20 ++++++++++++----- 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/django/contrib/gis/tests/geoapp/test_regress.py b/django/contrib/gis/tests/geoapp/test_regress.py index 043dace769..e2500308bb 100644 --- a/django/contrib/gis/tests/geoapp/test_regress.py +++ b/django/contrib/gis/tests/geoapp/test_regress.py @@ -28,6 +28,7 @@ class GeoRegressionTests(unittest.TestCase): kmz = render_to_kmz('gis/kml/placemarks.kml', {'places' : places}) @no_spatialite + @no_mysql def test03_extent(self): "Testing `extent` on a table with a single point, see #11827." pnt = City.objects.get(name='Pueblo').point diff --git a/django/contrib/gis/tests/layermap/models.py b/django/contrib/gis/tests/layermap/models.py index 5dbd528030..3a34d16f3f 100644 --- a/django/contrib/gis/tests/layermap/models.py +++ b/django/contrib/gis/tests/layermap/models.py @@ -29,6 +29,20 @@ class Interstate(models.Model): path = models.LineStringField() objects = models.GeoManager() +# Same as `City` above, but for testing model inheritance. +class CityBase(models.Model): + name = models.CharField(max_length=25) + population = models.IntegerField() + density = models.DecimalField(max_digits=7, decimal_places=1) + point = models.PointField() + objects = models.GeoManager() + +class ICity1(CityBase): + dt = models.DateField() + +class ICity2(ICity1): + dt_time = models.DateTimeField(auto_now=True) + # Mapping dictionaries for the models above. co_mapping = {'name' : 'Name', 'state' : {'name' : 'State'}, # ForeignKey's use another mapping dictionary for the _related_ Model (State in this case). diff --git a/django/contrib/gis/tests/layermap/tests.py b/django/contrib/gis/tests/layermap/tests.py index 56a9f2bdfe..b17e7b92fc 100644 --- a/django/contrib/gis/tests/layermap/tests.py +++ b/django/contrib/gis/tests/layermap/tests.py @@ -1,7 +1,7 @@ import os, unittest from copy import copy from decimal import Decimal -from models import City, County, CountyFeat, Interstate, State, city_mapping, co_mapping, cofeat_mapping, inter_mapping +from models import City, County, CountyFeat, Interstate, ICity1, ICity2, State, city_mapping, co_mapping, cofeat_mapping, inter_mapping from django.contrib.gis.db.backend import SpatialBackend from django.contrib.gis.utils.layermapping import LayerMapping, LayerMapError, InvalidDecimal, MissingForeignKey from django.contrib.gis.gdal import DataSource @@ -242,6 +242,26 @@ class LayerMapTest(unittest.TestCase): lm.save(step=st, strict=True) self.county_helper(county_feat=False) + def test06_model_inheritance(self): + "Tests LayerMapping on inherited models. See #12093." + icity_mapping = {'name' : 'Name', + 'population' : 'Population', + 'density' : 'Density', + 'point' : 'POINT', + 'dt' : 'Created', + } + + # Parent model has geometry field. + lm1 = LayerMapping(ICity1, city_shp, icity_mapping) + lm1.save() + + # Grandparent has geometry field. + lm2 = LayerMapping(ICity2, city_shp, icity_mapping) + lm2.save() + + self.assertEqual(6, ICity1.objects.count()) + self.assertEqual(3, ICity2.objects.count()) + def suite(): s = unittest.TestSuite() s.addTest(unittest.makeSuite(LayerMapTest)) diff --git a/django/contrib/gis/utils/layermapping.py b/django/contrib/gis/utils/layermapping.py index 43bc70a0ec..57c957811d 100644 --- a/django/contrib/gis/utils/layermapping.py +++ b/django/contrib/gis/utils/layermapping.py @@ -514,16 +514,26 @@ class LayerMapping(object): def geometry_column(self): "Returns the GeometryColumn model associated with the geographic column." from django.contrib.gis.models import GeometryColumns - # Getting the GeometryColumn object. + # Use the `get_field_by_name` on the model's options so that we + # get the correct model if there's model inheritance -- otherwise + # the returned model is None. + opts = self.model._meta + fld, model, direct, m2m = opts.get_field_by_name(self.geom_field) + if model is None: model = self.model + + # Trying to get the `GeometryColumns` object that corresponds to the + # the geometry field. try: - db_table = self.model._meta.db_table - geo_col = self.geom_field + db_table = model._meta.db_table + geo_col = fld.column + if SpatialBackend.oracle: # Making upper case for Oracle. db_table = db_table.upper() geo_col = geo_col.upper() - gc_kwargs = {GeometryColumns.table_name_col() : db_table, - GeometryColumns.geom_col_name() : geo_col, + + gc_kwargs = { GeometryColumns.table_name_col() : db_table, + GeometryColumns.geom_col_name() : geo_col, } return GeometryColumns.objects.get(**gc_kwargs) except Exception, msg: