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
@spookylukey spookylukey authored
View
9 django/db/models/query.py
@@ -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
View
20 tests/prefetch_related/models.py
@@ -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)
View
25 tests/prefetch_related/tests.py
@@ -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

@timgraham
Owner

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

@spookylukey
Collaborator
@timgraham
Owner

Thanks Luke, I've backported both commits.

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