From be89c9ababd85ec25606b39b408a2ab7ee6da357 Mon Sep 17 00:00:00 2001
From: Justin Bronn <jbronn@gmail.com>
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: