Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[1.6.x] Fixed #20955 -- select_related regression

In cases where the same connection (from model A to model B along the
same field) was needed multiple times in a select_related query, the
join setup code mistakenly reused an existing join.

Backpatch of 8d65b60.

Conflicts:

	django/db/models/sql/compiler.py
	tests/queries/tests.py
  • Loading branch information...
commit 161e26c2ec9f88bf0395941aaa2fd193b110affd 1 parent 69a4594
@akaariai akaariai authored
View
5 django/db/models/sql/compiler.py
@@ -687,9 +687,8 @@ def fill_related_selections(self, opts=None, root_alias=None, cur_depth=1,
# Use True here because we are looking at the _reverse_ side of
# the relation, which is always nullable.
new_nullable = True
- table = model._meta.db_table
- self.fill_related_selections(model._meta, table, cur_depth+1,
- next, restricted, new_nullable)
+ self.fill_related_selections(model._meta, alias, cur_depth + 1,
+ next, restricted, new_nullable)
def deferred_to_columns(self):
"""
View
26 tests/queries/models.py
@@ -497,3 +497,29 @@ class Meta:
def __str__(self):
return '%s' % self.pk
+
+class BaseUser(models.Model):
+ pass
+
+@python_2_unicode_compatible
+class Task(models.Model):
+ title = models.CharField(max_length=10)
+ owner = models.ForeignKey(BaseUser, related_name='owner')
+ creator = models.ForeignKey(BaseUser, related_name='creator')
+
+ def __str__(self):
+ return self.title
+
+@python_2_unicode_compatible
+class Staff(models.Model):
+ name = models.CharField(max_length=10)
+
+ def __str__(self):
+ return self.name
+
+@python_2_unicode_compatible
+class StaffUser(BaseUser):
+ staff = models.OneToOneField(Staff, related_name='user')
+
+ def __str__(self):
+ return self.staff
View
22 tests/queries/tests.py
@@ -25,7 +25,7 @@
OneToOneCategory, NullableName, ProxyCategory, SingleObject, RelatedObject,
ModelA, ModelB, ModelC, ModelD, Responsibility, Job, JobResponsibilities,
BaseA, FK1, Identifier, Program, Channel, Page, Paragraph, Chapter, Book,
- MyObject, Order, OrderItem)
+ MyObject, Order, OrderItem, Task, Staff, StaffUser)
class BaseQuerysetTest(TestCase):
@@ -2943,3 +2943,23 @@ def test_wrong_type_lookup(self):
self.assertQuerysetEqual(
ObjectB.objects.filter(objecta__in=[wrong_type]),
[ob], lambda x: x)
+
+class Ticket20955Tests(TestCase):
+ def test_ticket_20955(self):
+ jack = Staff.objects.create(name='jackstaff')
+ jackstaff = StaffUser.objects.create(staff=jack)
+ jill = Staff.objects.create(name='jillstaff')
+ jillstaff = StaffUser.objects.create(staff=jill)
+ task = Task.objects.create(creator=jackstaff, owner=jillstaff, title="task")
+ task_get = Task.objects.get(pk=task.pk)
+ # Load data so that assertNumQueries doesn't complain about the get
+ # version's queries.
+ task_get.creator.staffuser.staff
+ task_get.owner.staffuser.staff
+ task_select_related = Task.objects.select_related(
+ 'creator__staffuser__staff', 'owner__staffuser__staff').get(pk=task.pk)
+ with self.assertNumQueries(0):
+ self.assertEqual(task_select_related.creator.staffuser.staff,
+ task_get.creator.staffuser.staff)
+ self.assertEqual(task_select_related.owner.staffuser.staff,
+ task_get.owner.staffuser.staff)
Please sign in to comment.
Something went wrong with that request. Please try again.