Skip to content
Permalink
Browse files

[1.6.x] Fixed #21410 -- prefetch_related() for ForeignKeys with relat…

…ed_name='+'

Regression introduced by commit 9777442.

Thanks to trac username troygrosfield for the report and test case.

Backpatch of cb83448 from master.

Conflicts:

	tests/prefetch_related/models.py
  • Loading branch information...
loic authored and akaariai committed Nov 13, 2013
1 parent b6acc4f commit b107421acfc4046ffaa799aceef2c3b4877207f2
Showing with 53 additions and 2 deletions.
  1. +11 −1 django/db/models/fields/related.py
  2. +15 −0 tests/prefetch_related/models.py
  3. +27 −1 tests/prefetch_related/tests.py
@@ -273,7 +273,17 @@ def get_prefetch_queryset(self, instances):
rel_obj_attr = self.field.get_foreign_related_value
instance_attr = self.field.get_local_related_value
instances_dict = dict((instance_attr(inst), inst) for inst in instances)
query = {'%s__in' % self.field.related_query_name(): instances}
related_field = self.field.foreign_related_fields[0]

# FIXME: This will need to be revisited when we introduce support for
# composite fields. In the meantime we take this practical approach to
# solve a regression on 1.6 when the reverse manager in hidden
# (related_name ends with a '+'). Refs #21410.
if self.field.rel.is_hidden():
query = {'%s__in' % related_field.name: set(instance_attr(inst)[0] for inst in instances)}
else:
query = {'%s__in' % self.field.related_query_name(): instances}

qs = self.get_queryset(instance=instances[0]).filter(**query)
# Since we're going to assign directly in the cache,
# we must manage the reverse relation cache manually.
@@ -215,3 +215,18 @@ class WordEntry(models.Model):

def __str__(self):
return "%s (%s)" % (self.name, self.id)


## Ticket #21410: Regression when related_name="+"

@python_2_unicode_compatible
class Author2(models.Model):
name = models.CharField(max_length=50, unique=True)
first_book = models.ForeignKey('Book', related_name='first_time_authors+')
favorite_books = models.ManyToManyField('Book', related_name='+')

def __str__(self):
return self.name

class Meta:
ordering = ['id']
@@ -9,7 +9,7 @@
from .models import (Author, Book, Reader, Qualification, Teacher, Department,
TaggedItem, Bookmark, AuthorAddress, FavoriteAuthors, AuthorWithAge,
BookWithYear, BookReview, Person, House, Room, Employee, Comment,
LessonEntry, WordEntry)
LessonEntry, WordEntry, Author2)


class PrefetchRelatedTests(TestCase):
@@ -651,3 +651,29 @@ def setUp(self):

def test_bug(self):
list(WordEntry.objects.prefetch_related('lesson_entry', 'lesson_entry__wordentry_set'))


class Ticket21410Tests(TestCase):

def setUp(self):
self.book1 = Book.objects.create(title="Poems")
self.book2 = Book.objects.create(title="Jane Eyre")
self.book3 = Book.objects.create(title="Wuthering Heights")
self.book4 = Book.objects.create(title="Sense and Sensibility")

self.author1 = Author2.objects.create(name="Charlotte",
first_book=self.book1)
self.author2 = Author2.objects.create(name="Anne",
first_book=self.book1)
self.author3 = Author2.objects.create(name="Emily",
first_book=self.book1)
self.author4 = Author2.objects.create(name="Jane",
first_book=self.book4)

self.author1.favorite_books.add(self.book1, self.book2, self.book3)
self.author2.favorite_books.add(self.book1)
self.author3.favorite_books.add(self.book2)
self.author4.favorite_books.add(self.book3)

def test_bug(self):
list(Author2.objects.prefetch_related('first_book', 'favorite_books'))

0 comments on commit b107421

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.