Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #19607 - prefetch_related crash

Thanks to av@rdf.ru and flarno11@yahoo.de for the report.
  • Loading branch information...
commit 4fd94969d859eb25680a5a52ed482c8f22e5ee15 1 parent 48424ad
Luke Plant spookylukey authored
9 django/db/models/query.py
View
@@ -1558,8 +1558,13 @@ def prefetch_related_objects(result_cache, related_lookups):
good_objects = False
break
else:
- # We already did this list
- break
+ # Since prefetching can re-use instances, it is possible to
+ # have the same instance multiple times in obj_list. So we
+ # can reach this branch either because we did all of
+ # obj_list already, or because we did 'obj' earlier in this
+ # iteration over obj_list. In the first case we could
+ # shortcut and exit the loop, but not in the second.
+ continue
if not good_objects:
break
20 tests/prefetch_related/models.py
View
@@ -195,3 +195,23 @@ def __str__(self):
class Meta:
ordering = ['id']
+
+
+### Ticket 19607
+
+@python_2_unicode_compatible
+class LessonEntry(models.Model):
+ name1 = models.CharField(max_length=200)
+ name2 = models.CharField(max_length=200)
+
+ def __str__(self):
+ return "%s %s" % (self.name1, self.name2)
+
+
+@python_2_unicode_compatible
+class WordEntry(models.Model):
+ lesson_entry = models.ForeignKey(LessonEntry)
+ name = models.CharField(max_length=200)
+
+ def __str__(self):
+ return "%s (%s)" % (self.name, self.id)
25 tests/prefetch_related/tests.py
View
@@ -8,7 +8,8 @@
from .models import (Author, Book, Reader, Qualification, Teacher, Department,
TaggedItem, Bookmark, AuthorAddress, FavoriteAuthors, AuthorWithAge,
- BookWithYear, BookReview, Person, House, Room, Employee, Comment)
+ BookWithYear, BookReview, Person, House, Room, Employee, Comment,
+ LessonEntry, WordEntry)
class PrefetchRelatedTests(TestCase):
@@ -618,3 +619,25 @@ def test_using_is_honored_inheritance(self):
ages = ", ".join(str(a.authorwithage.age) for a in A.prefetch_related('authorwithage'))
self.assertEqual(ages, "50, 49")
+
+
+class Ticket19607Tests(TestCase):
+
+ def setUp(self):
+
+ for id, name1, name2 in [
+ (1, 'einfach', 'simple'),
+ (2, 'schwierig', 'difficult'),
+ ]:
+ LessonEntry.objects.create(id=id, name1=name1, name2=name2)
+
+ for id, lesson_entry_id, name in [
+ (1, 1, 'einfach'),
+ (2, 1, 'simple'),
+ (3, 2, 'schwierig'),
+ (4, 2, 'difficult'),
+ ]:
+ WordEntry.objects.create(id=id, lesson_entry_id=lesson_entry_id, name=name)
+
+ def test_bug(self):
+ list(WordEntry.objects.prefetch_related('lesson_entry', 'lesson_entry__wordentry_set'))

3 comments on commit 4fd9496

Tim Graham
Owner

Luke, any objection to backporting to 1.5.x? The cherry pick merges cleanly and the tests pass.

Luke Plant
Collaborator
Tim Graham
Owner

Thanks Luke, I've backported both commits.

Please sign in to comment.
Something went wrong with that request. Please try again.