mirror of
https://github.com/django/django.git
synced 2024-12-23 01:25:58 +00:00
Fixed #19870 -- Regression in select_related in inheritance cases
There was a regression in case two models inherited the same parent,
and one contained a foreign key to other. When select_related travelled
the foreign key the other model reused the parent join made by the
first model. This was likely caused by Query.join_parent_model()
addition in commit 68985db482
.
Thanks to Trac alias loic84 for report & tests.
This commit is contained in:
parent
649118961c
commit
3c6318e831
@ -265,14 +265,19 @@ class SQLCompiler(object):
|
||||
qn2 = self.connection.ops.quote_name
|
||||
aliases = set()
|
||||
only_load = self.deferred_to_columns()
|
||||
seen = self.query.included_inherited_models.copy()
|
||||
if start_alias:
|
||||
seen[None] = start_alias
|
||||
if not start_alias:
|
||||
start_alias = self.query.get_initial_alias()
|
||||
# The 'seen_models' is used to optimize checking the needed parent
|
||||
# alias for a given field. This also includes None -> start_alias to
|
||||
# be used by local fields.
|
||||
seen_models = {None: start_alias}
|
||||
|
||||
for field, model in opts.get_fields_with_model():
|
||||
if from_parent and model is not None and issubclass(from_parent, model):
|
||||
# Avoid loading data for already loaded parents.
|
||||
continue
|
||||
alias = self.query.join_parent_model(opts, model, start_alias, seen)
|
||||
alias = self.query.join_parent_model(opts, model, start_alias,
|
||||
seen_models)
|
||||
table = self.query.alias_map[alias].table_name
|
||||
if table in only_load and field.column not in only_load[table]:
|
||||
continue
|
||||
|
@ -94,3 +94,17 @@ class Item(models.Model):
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
# Models for testing bug #19870.
|
||||
@python_2_unicode_compatible
|
||||
class Fowl(models.Model):
|
||||
name = models.CharField(max_length=10)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Hen(Fowl):
|
||||
pass
|
||||
|
||||
class Chick(Fowl):
|
||||
mother = models.ForeignKey(Hen)
|
||||
|
@ -5,7 +5,7 @@ from django.utils import six
|
||||
|
||||
from .models import (Building, Child, Device, Port, Item, Country, Connection,
|
||||
ClientStatus, State, Client, SpecialClient, TUser, Person, Student,
|
||||
Organizer, Class, Enrollment)
|
||||
Organizer, Class, Enrollment, Hen, Chick)
|
||||
|
||||
|
||||
class SelectRelatedRegressTests(TestCase):
|
||||
@ -162,3 +162,14 @@ class SelectRelatedRegressTests(TestCase):
|
||||
# The select_related join was promoted as there is already an
|
||||
# existing join.
|
||||
self.assertTrue('LEFT OUTER' in str(qs.query))
|
||||
|
||||
def test_regression_19870(self):
|
||||
"""
|
||||
Regression for #19870
|
||||
|
||||
"""
|
||||
hen = Hen.objects.create(name='Hen')
|
||||
chick = Chick.objects.create(name='Chick', mother=hen)
|
||||
|
||||
self.assertEqual(Chick.objects.all()[0].mother.name, 'Hen')
|
||||
self.assertEqual(Chick.objects.select_related()[0].mother.name, 'Hen')
|
||||
|
Loading…
Reference in New Issue
Block a user