Fixed #18309 - Prefetch related does not work for fkey to multitable inherited model

Thanks to milosu for the report, tests and initial patch.
This commit is contained in:
Luke Plant 2012-06-06 14:17:32 +01:00
parent f0664dc8ae
commit 4fea46a030
3 changed files with 16 additions and 3 deletions

View File

@ -329,10 +329,10 @@ class ReverseSingleRelatedObjectDescriptor(object):
return QuerySet(self.field.rel.to).using(db) return QuerySet(self.field.rel.to).using(db)
def get_prefetch_query_set(self, instances): def get_prefetch_query_set(self, instances):
rel_obj_attr = attrgetter(self.field.rel.field_name) other_field = self.field.rel.get_related_field()
rel_obj_attr = attrgetter(other_field.attname)
instance_attr = attrgetter(self.field.attname) instance_attr = attrgetter(self.field.attname)
instances_dict = dict((instance_attr(inst), inst) for inst in instances) instances_dict = dict((instance_attr(inst), inst) for inst in instances)
other_field = self.field.rel.get_related_field()
if other_field.rel: if other_field.rel:
params = {'%s__pk__in' % self.field.rel.field_name: instances_dict.keys()} params = {'%s__pk__in' % self.field.rel.field_name: instances_dict.keys()}
else: else:

View File

@ -68,6 +68,9 @@ class Reader(models.Model):
class Meta: class Meta:
ordering = ['id'] ordering = ['id']
class BookReview(models.Model):
book = models.ForeignKey(BookWithYear)
notes = models.TextField(null=True, blank=True)
## Models for default manager tests ## Models for default manager tests

View File

@ -7,7 +7,7 @@ from django.test.utils import override_settings
from .models import (Author, Book, Reader, Qualification, Teacher, Department, from .models import (Author, Book, Reader, Qualification, Teacher, Department,
TaggedItem, Bookmark, AuthorAddress, FavoriteAuthors, AuthorWithAge, TaggedItem, Bookmark, AuthorAddress, FavoriteAuthors, AuthorWithAge,
BookWithYear, Person, House, Room, Employee, Comment) BookWithYear, BookReview, Person, House, Room, Employee, Comment)
class PrefetchRelatedTests(TestCase): class PrefetchRelatedTests(TestCase):
@ -335,6 +335,10 @@ class MultiTableInheritanceTest(TestCase):
self.authorAddress = AuthorAddress.objects.create( self.authorAddress = AuthorAddress.objects.create(
author=self.author1, address='SomeStreet 1') author=self.author1, address='SomeStreet 1')
self.book2.aged_authors.add(self.author2, self.author3) self.book2.aged_authors.add(self.author2, self.author3)
self.br1 = BookReview.objects.create(
book=self.book1, notes="review book1")
self.br2 = BookReview.objects.create(
book=self.book2, notes="review book2")
def test_foreignkey(self): def test_foreignkey(self):
with self.assertNumQueries(2): with self.assertNumQueries(2):
@ -343,6 +347,12 @@ class MultiTableInheritanceTest(TestCase):
for obj in qs] for obj in qs]
self.assertEqual(addresses, [[unicode(self.authorAddress)], [], []]) self.assertEqual(addresses, [[unicode(self.authorAddress)], [], []])
def test_foreignkey_to_inherited(self):
with self.assertNumQueries(2):
qs = BookReview.objects.prefetch_related('book')
titles = [obj.book.title for obj in qs]
self.assertEquals(titles, ["Poems", "More poems"])
def test_m2m_to_inheriting_model(self): def test_m2m_to_inheriting_model(self):
qs = AuthorWithAge.objects.prefetch_related('books_with_year') qs = AuthorWithAge.objects.prefetch_related('books_with_year')
with self.assertNumQueries(2): with self.assertNumQueries(2):