summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMalcolm Tredinnick <malcolm.tredinnick@gmail.com>2008-08-26 20:44:20 +0000
committerMalcolm Tredinnick <malcolm.tredinnick@gmail.com>2008-08-26 20:44:20 +0000
commit8f5234d801ebd2e8b526d4c75c94c89ea21eb440 (patch)
tree936310bd01f6316783001358277352b5a3d9956b
parent6056ab1beed04f53013ee83fc82303b5c42c9fbd (diff)
Fixed #8036 -- Fixed a case when attempting to traverse non-existent related
instances. We weren't skipping the correct output columns before processing subsequent existing related instances. Thanks to mrmachine for the test case. git-svn-id: http://code.djangoproject.com/svn/django/trunk@8598 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--django/db/models/query.py8
-rw-r--r--tests/regressiontests/select_related_regress/models.py40
2 files changed, 45 insertions, 3 deletions
diff --git a/django/db/models/query.py b/django/db/models/query.py
index 2ff1c26344..c5e9cce90a 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -794,8 +794,9 @@ def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0,
fields = row[index_start:index_end]
if not [x for x in fields if x is not None]:
# If we only have a list of Nones, there was not related object.
- return None, index_end
- obj = klass(*fields)
+ obj = None
+ else:
+ obj = klass(*fields)
for f in klass._meta.fields:
if not select_related_descend(f, restricted, requested):
continue
@@ -807,7 +808,8 @@ def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0,
cur_depth+1, next)
if cached_row:
rel_obj, index_end = cached_row
- setattr(obj, f.get_cache_name(), rel_obj)
+ if obj is not None:
+ setattr(obj, f.get_cache_name(), rel_obj)
return obj, index_end
diff --git a/tests/regressiontests/select_related_regress/models.py b/tests/regressiontests/select_related_regress/models.py
index 163dc59164..eca620ccf7 100644
--- a/tests/regressiontests/select_related_regress/models.py
+++ b/tests/regressiontests/select_related_regress/models.py
@@ -49,6 +49,22 @@ class Enrollment(models.Model):
std = models.ForeignKey(Student)
cls = models.ForeignKey(Class)
+# Models for testing bug #8036.
+class Country(models.Model):
+ name = models.CharField(max_length=50)
+
+class State(models.Model):
+ name = models.CharField(max_length=50)
+ country = models.ForeignKey(Country)
+
+class ClientStatus(models.Model):
+ name = models.CharField(max_length=50)
+
+class Client(models.Model):
+ name = models.CharField(max_length=50)
+ state = models.ForeignKey(State, null=True)
+ status = models.ForeignKey(ClientStatus)
+
__test__ = {'API_TESTS': """
Regression test for bug #7110. When using select_related(), we must query the
Device and Building tables using two different aliases (each) in order to
@@ -100,4 +116,28 @@ separate).
u"std"
>>> e_related.cls.org.person.user.name
u"org"
+
+Regression test for bug #8036: the first related model in the tests below
+("state") is empty and we try to select the more remotely related
+state__country. The regression here was not skipping the empty column results
+for country before getting status.
+
+>>> australia = Country.objects.create(name='Australia')
+>>> active = ClientStatus.objects.create(name='active')
+>>> client = Client.objects.create(name='client', status=active)
+
+>>> client.status
+<ClientStatus: ClientStatus object>
+>>> Client.objects.select_related()[0].status
+<ClientStatus: ClientStatus object>
+>>> Client.objects.select_related('state')[0].status
+<ClientStatus: ClientStatus object>
+>>> Client.objects.select_related('state', 'status')[0].status
+<ClientStatus: ClientStatus object>
+>>> Client.objects.select_related('state__country')[0].status
+<ClientStatus: ClientStatus object>
+>>> Client.objects.select_related('state__country', 'status')[0].status
+<ClientStatus: ClientStatus object>
+>>> Client.objects.select_related('status')[0].status
+<ClientStatus: ClientStatus object>
"""}