diff --git a/django/forms/models.py b/django/forms/models.py index 8134cf3de3..414a9eafe4 100644 --- a/django/forms/models.py +++ b/django/forms/models.py @@ -1132,7 +1132,7 @@ class ModelChoiceIterator: yield ("", self.field.empty_label) queryset = self.queryset # Can't use iterator() when queryset uses prefetch_related() - if not queryset._prefetch_related_lookups: + if not queryset._prefetch_related_lookups and queryset._result_cache is None: queryset = queryset.iterator() for obj in queryset: yield self.choice(obj) diff --git a/tests/model_forms/test_modelchoicefield.py b/tests/model_forms/test_modelchoicefield.py index 6b0f00cf7f..733175823f 100644 --- a/tests/model_forms/test_modelchoicefield.py +++ b/tests/model_forms/test_modelchoicefield.py @@ -257,6 +257,17 @@ class ModelChoiceFieldTests(TestCase): (self.c3.pk, 'Third'), ]) + def test_queryset_result_cache_is_reused(self): + f = forms.ModelChoiceField(Category.objects.all()) + with self.assertNumQueries(1): + # list() calls __len__() and __iter__(); no duplicate queries. + self.assertEqual(list(f.choices), [ + ('', '---------'), + (self.c1.pk, 'Entertainment'), + (self.c2.pk, 'A test'), + (self.c3.pk, 'Third'), + ]) + def test_num_queries(self): """ Widgets that render multiple subwidgets shouldn't make more than one