Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[1.5.x] Fixed #16436 -- defer + annotate + select_related crash

Correctly calculate the ``aggregate_start`` offset from loaded fields,
if any are deferred, instead of ``self.query.select`` which includes all
fields on the model.

Backpatch of 69f7db1 from master.
  • Loading branch information...
commit b495c24375aa1fe0373727511cf81298337a1227 1 parent f8393ed
Tai Lee authored akaariai committed
View
3  django/db/models/sql/compiler.py
@@ -775,7 +775,8 @@ def results_iter(self):
for rows in self.execute_sql(MULTI):
for row in rows:
if has_aggregate_select:
- aggregate_start = len(self.query.extra_select) + len(self.query.select)
+ loaded_fields = self.query.get_loaded_field_names().get(self.query.model, set()) or self.query.select
+ aggregate_start = len(self.query.extra_select) + len(loaded_fields)
aggregate_end = aggregate_start + len(self.query.aggregate_select)
if resolve_columns:
if fields is None:
View
19 tests/modeltests/defer/models.py
@@ -28,3 +28,22 @@ class BigChild(Primary):
class ChildProxy(Child):
class Meta:
proxy=True
+
+class Profile(models.Model):
+ profile1 = models.TextField(default='profile1')
+
+class Location(models.Model):
+ location1 = models.TextField(default='location1')
+
+class Item(models.Model):
+ pass
+
+class Request(models.Model):
+ profile = models.ForeignKey(Profile, null=True, blank=True)
+ location = models.ForeignKey(Location)
+ items = models.ManyToManyField(Item)
+
+ request1 = models.TextField(default='request1')
+ request2 = models.TextField(default='request2')
+ request3 = models.TextField(default='request3')
+ request4 = models.TextField(default='request4')
View
17 tests/modeltests/defer/tests.py
@@ -1,9 +1,10 @@
from __future__ import absolute_import
+from django.db.models import Count
from django.db.models.query_utils import DeferredAttribute, InvalidQuery
from django.test import TestCase
-from .models import Secondary, Primary, Child, BigChild, ChildProxy
+from .models import Secondary, Primary, Child, BigChild, ChildProxy, Location, Request
class DeferTests(TestCase):
@@ -183,3 +184,17 @@ def test_defer_inheritance_pk_chaining(self):
with self.assertNumQueries(0):
bc_deferred.id
self.assertEqual(bc_deferred.pk, bc_deferred.id)
+
+class DeferAnnotateSelectRelatedTest(TestCase):
+ def test_defer_annotate_select_related(self):
+ location = Location.objects.create()
+ Request.objects.create(location=location)
+ self.assertIsInstance(list(Request.objects
+ .annotate(Count('items')).select_related('profile', 'location')
+ .only('profile', 'location')), list)
+ self.assertIsInstance(list(Request.objects
+ .annotate(Count('items')).select_related('profile', 'location')
+ .only('profile__profile1', 'location__location1')), list)
+ self.assertIsInstance(list(Request.objects
+ .annotate(Count('items')).select_related('profile', 'location')
+ .defer('request1', 'request2', 'request3', 'request4')), list)
Please sign in to comment.
Something went wrong with that request. Please try again.