[1.5.x] Fixed #19607 - prefetch_related crash

Thanks to av@rdf.ru and flarno11@yahoo.de for the report.

Backport of 4fd94969d8 from master
This commit is contained in:
Luke Plant 2013-05-24 10:01:34 +01:00 committed by Tim Graham
parent 9356495936
commit 00b39e0145
3 changed files with 51 additions and 3 deletions

View File

@ -1726,8 +1726,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 File

@ -195,3 +195,23 @@ class Employee(models.Model):
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 File

@ -8,7 +8,8 @@ from django.utils import six
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 @@ class MultiDbTests(TestCase):
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'))