Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
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...
commit b107421acfc4046ffaa799aceef2c3b4877207f2 1 parent b6acc4f
@loic loic authored akaariai committed
View
12 django/db/models/fields/related.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.
View
15 tests/prefetch_related/models.py
@@ -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']
View
28 tests/prefetch_related/tests.py
@@ -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'))
Please sign in to comment.
Something went wrong with that request. Please try again.