diff --git a/django/contrib/gis/db/models/sql/compiler.py b/django/contrib/gis/db/models/sql/compiler.py index 78eeeafe190..55dc4a66ec4 100644 --- a/django/contrib/gis/db/models/sql/compiler.py +++ b/django/contrib/gis/db/models/sql/compiler.py @@ -95,7 +95,7 @@ class GeoSQLCompiler(compiler.SQLCompiler): return result def get_default_columns(self, with_aliases=False, col_aliases=None, - start_alias=None, opts=None, as_pairs=False): + start_alias=None, opts=None, as_pairs=False, local_only=False): """ Computes the default columns for selecting every field in the base model. Will sometimes be called to pull in related models (e.g. via @@ -121,6 +121,8 @@ class GeoSQLCompiler(compiler.SQLCompiler): if start_alias: seen = {None: start_alias} for field, model in opts.get_fields_with_model(): + if local_only and model is not None: + continue if start_alias: try: alias = seen[model] diff --git a/django/contrib/gis/tests/relatedapp/models.py b/django/contrib/gis/tests/relatedapp/models.py index 726f9826c0a..2e9a62b61f2 100644 --- a/django/contrib/gis/tests/relatedapp/models.py +++ b/django/contrib/gis/tests/relatedapp/models.py @@ -38,6 +38,11 @@ class Author(models.Model): name = models.CharField(max_length=100) objects = models.GeoManager() +class Article(models.Model): + title = models.CharField(max_length=100) + author = models.ForeignKey(Author, unique=True) + objects = models.GeoManager() + class Book(models.Model): title = models.CharField(max_length=100) author = models.ForeignKey(Author, related_name='books', null=True) diff --git a/django/contrib/gis/tests/relatedapp/tests.py b/django/contrib/gis/tests/relatedapp/tests.py index 184b65b9c72..5d3d00f08d9 100644 --- a/django/contrib/gis/tests/relatedapp/tests.py +++ b/django/contrib/gis/tests/relatedapp/tests.py @@ -4,7 +4,7 @@ from django.contrib.gis.db.models import Collect, Count, Extent, F, Union from django.contrib.gis.geometry.backend import Geometry from django.contrib.gis.tests.utils import mysql, oracle, postgis, spatialite, no_mysql, no_oracle, no_spatialite from django.conf import settings -from models import City, Location, DirectoryEntry, Parcel, Book, Author +from models import City, Location, DirectoryEntry, Parcel, Book, Author, Article cities = (('Aurora', 'TX', -97.516111, 33.058333), ('Roswell', 'NM', -104.528056, 33.387222), @@ -291,6 +291,14 @@ class RelatedGeoModelTest(unittest.TestCase): self.assertEqual(4, len(coll)) self.assertEqual(ref_geom, coll) + def test15_invalid_select_related(self): + "Testing doing select_related on the related name manager of a unique FK. See #13934." + qs = Article.objects.select_related('author__article') + # This triggers TypeError when `get_default_columns` has no `local_only` + # keyword. The TypeError is swallowed if QuerySet is actually + # evaluated as list generation swallows TypeError in CPython. + sql = str(qs.query) + # TODO: Related tests for KML, GML, and distance lookups. def suite():