[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 8d65b6082c
.
Conflicts:
django/db/models/sql/compiler.py
tests/queries/tests.py
This commit is contained in:
parent
69a4594cb7
commit
161e26c2ec
|
@ -687,8 +687,7 @@ class SQLCompiler(object):
|
||||||
# Use True here because we are looking at the _reverse_ side of
|
# Use True here because we are looking at the _reverse_ side of
|
||||||
# the relation, which is always nullable.
|
# the relation, which is always nullable.
|
||||||
new_nullable = True
|
new_nullable = True
|
||||||
table = model._meta.db_table
|
self.fill_related_selections(model._meta, alias, cur_depth + 1,
|
||||||
self.fill_related_selections(model._meta, table, cur_depth+1,
|
|
||||||
next, restricted, new_nullable)
|
next, restricted, new_nullable)
|
||||||
|
|
||||||
def deferred_to_columns(self):
|
def deferred_to_columns(self):
|
||||||
|
|
|
@ -497,3 +497,29 @@ class OrderItem(models.Model):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '%s' % self.pk
|
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
|
||||||
|
|
|
@ -25,7 +25,7 @@ from .models import (
|
||||||
OneToOneCategory, NullableName, ProxyCategory, SingleObject, RelatedObject,
|
OneToOneCategory, NullableName, ProxyCategory, SingleObject, RelatedObject,
|
||||||
ModelA, ModelB, ModelC, ModelD, Responsibility, Job, JobResponsibilities,
|
ModelA, ModelB, ModelC, ModelD, Responsibility, Job, JobResponsibilities,
|
||||||
BaseA, FK1, Identifier, Program, Channel, Page, Paragraph, Chapter, Book,
|
BaseA, FK1, Identifier, Program, Channel, Page, Paragraph, Chapter, Book,
|
||||||
MyObject, Order, OrderItem)
|
MyObject, Order, OrderItem, Task, Staff, StaffUser)
|
||||||
|
|
||||||
|
|
||||||
class BaseQuerysetTest(TestCase):
|
class BaseQuerysetTest(TestCase):
|
||||||
|
@ -2943,3 +2943,23 @@ class RelatedLookupTypeTests(TestCase):
|
||||||
self.assertQuerysetEqual(
|
self.assertQuerysetEqual(
|
||||||
ObjectB.objects.filter(objecta__in=[wrong_type]),
|
ObjectB.objects.filter(objecta__in=[wrong_type]),
|
||||||
[ob], lambda x: x)
|
[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)
|
||||||
|
|
Loading…
Reference in New Issue