Author: jbronn
Date: 2009-04-07 16:33:43 -0500 (Tue, 07 Apr 2009)
New Revision: 10437

Modified:
   django/branches/releases/1.0.X/django/contrib/gis/db/models/sql/query.py
   django/branches/releases/1.0.X/django/contrib/gis/tests/relatedapp/tests.py
Log:
[1.0.X] Fixed #10757 -- Fixed improper selection of primary keys across 
relations when using `GeoManager.values`.  Thanks, David Gouldin for ticket and 
initial patch.

Backport of r10434 from trunk.


Modified: 
django/branches/releases/1.0.X/django/contrib/gis/db/models/sql/query.py
===================================================================
--- django/branches/releases/1.0.X/django/contrib/gis/db/models/sql/query.py    
2009-04-07 21:21:17 UTC (rev 10436)
+++ django/branches/releases/1.0.X/django/contrib/gis/db/models/sql/query.py    
2009-04-07 21:33:43 UTC (rev 10437)
@@ -66,7 +66,7 @@
             # This loop customized for GeoQuery.
             for col, field in izip(self.select, self.select_fields):
                 if isinstance(col, (list, tuple)):
-                    r = self.get_field_select(field, col[0])
+                    r = self.get_field_select(field, col[0], col[1])
                     if with_aliases and col[1] in col_aliases:
                         c_alias = 'Col%d' % len(col_aliases)
                         result.append('%s AS %s' % (r, c_alias))
@@ -89,7 +89,7 @@
         # This loop customized for GeoQuery.
         if not self.aggregate:
             for (table, col), field in izip(self.related_select_cols, 
self.related_select_fields):
-                r = self.get_field_select(field, table)
+                r = self.get_field_select(field, table, col)
                 if with_aliases and col in col_aliases:
                     c_alias = 'Col%d' % len(col_aliases)
                     result.append('%s AS %s' % (r, c_alias))
@@ -219,19 +219,20 @@
             sel_fmt = sel_fmt % self.custom_select[alias]
         return sel_fmt
 
-    def get_field_select(self, fld, alias=None):
+    def get_field_select(self, field, alias=None, column=None):
         """
         Returns the SELECT SQL string for the given field.  Figures out
-        if any custom selection SQL is needed for the column  The `alias` 
-        keyword may be used to manually specify the database table where 
-        the column exists, if not in the model associated with this 
-        `GeoQuery`.
+        if any custom selection SQL is needed for the column  The `alias`
+        keyword may be used to manually specify the database table where
+        the column exists, if not in the model associated with this
+        `GeoQuery`.  Similarly, `column` may be used to specify the exact
+        column name, rather than using the `column` attribute on `field`.
         """
-        sel_fmt = self.get_select_format(fld)
-        if fld in self.custom_select:
-            field_sel = sel_fmt % self.custom_select[fld]
+        sel_fmt = self.get_select_format(field)
+        if field in self.custom_select:
+            field_sel = sel_fmt % self.custom_select[field]
         else:
-            field_sel = sel_fmt % self._field_column(fld, alias)
+            field_sel = sel_fmt % self._field_column(field, alias, column)
         return field_sel
 
     def get_select_format(self, fld):
@@ -293,17 +294,18 @@
         else:
             return False
 
-    def _field_column(self, field, table_alias=None):
+    def _field_column(self, field, table_alias=None, column=None):
         """
         Helper function that returns the database column for the given field.
         The table and column are returned (quoted) in the proper format, e.g.,
-        `"geoapp_city"."point"`.  If `table_alias` is not specified, the 
+        `"geoapp_city"."point"`.  If `table_alias` is not specified, the
         database table associated with the model of this `GeoQuery` will be
-        used.
+        used.  If `column` is specified, it will be used instead of the value
+        in `field.column`.
         """
         if table_alias is None: table_alias = self.model._meta.db_table
-        return "%s.%s" % (self.quote_name_unless_alias(table_alias), 
-                          self.connection.ops.quote_name(field.column))
+        return "%s.%s" % (self.quote_name_unless_alias(table_alias),
+                          self.connection.ops.quote_name(column or 
field.column))
 
     def _geo_field(self, field_name=None):
         """

Modified: 
django/branches/releases/1.0.X/django/contrib/gis/tests/relatedapp/tests.py
===================================================================
--- django/branches/releases/1.0.X/django/contrib/gis/tests/relatedapp/tests.py 
2009-04-07 21:21:17 UTC (rev 10436)
+++ django/branches/releases/1.0.X/django/contrib/gis/tests/relatedapp/tests.py 
2009-04-07 21:33:43 UTC (rev 10437)
@@ -95,6 +95,26 @@
         # Regression test for #9752.
         l = list(DirectoryEntry.objects.all().select_related())
 
+    def test09_pk_relations(self):
+        "Ensuring correct primary key column is selected across relations. See 
#10757."
+        # Adding two more cities, but this time making sure that their location
+        # ID values do not match their City ID values.
+        loc1 = Location.objects.create(point='POINT (-95.363151 29.763374)')
+        loc2 = Location.objects.create(point='POINT (-96.801611 32.782057)')
+        dallas = City.objects.create(name='Dallas', location=loc2)
+        houston = City.objects.create(name='Houston', location=loc1)
+
+        # The expected ID values -- notice the last two location IDs
+        # are out of order.  We want to make sure that the related
+        # location ID column is selected instead of ID column for
+        # the city.
+        city_ids = (1, 2, 3, 4, 5)
+        loc_ids = (1, 2, 3, 5, 4)
+        ids_qs = City.objects.order_by('id').values('id', 'location__id')
+        for val_dict, c_id, l_id in zip(ids_qs, city_ids, loc_ids):
+            self.assertEqual(val_dict['id'], c_id)
+            self.assertEqual(val_dict['location__id'], l_id)
+
     # TODO: Related tests for KML, GML, and distance lookups.
         
 def suite():


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to