Loading django/forms/models.py +3 −1 Original line number Diff line number Diff line Loading @@ -1102,7 +1102,9 @@ class ModelChoiceIterator(object): def __iter__(self): if self.field.empty_label is not None: yield ("", self.field.empty_label) for obj in self.queryset.iterator(): # Can't use iterator() when queryset uses prefetch_related() method = 'all' if self.queryset._prefetch_related_lookups else 'iterator' for obj in getattr(self.queryset, method)(): yield self.choice(obj) def __len__(self): Loading docs/releases/1.8.6.txt +2 −1 Original line number Diff line number Diff line Loading @@ -9,4 +9,5 @@ Django 1.8.6 fixes several bugs in 1.8.5. Bugfixes ======== * ... * Fixed a regression causing ``ModelChoiceField`` to ignore ``prefetch_related()`` on its queryset (:ticket:`25496`). tests/model_forms/tests.py +23 −0 Original line number Diff line number Diff line Loading @@ -2285,6 +2285,29 @@ class OtherModelFormTests(TestCase): with self.assertRaises(ValidationError): f.fields['status'].clean('z') def test_prefetch_related_queryset(self): """ ModelChoiceField should respect a prefetch_related() on its queryset. """ blue = Colour.objects.create(name='blue') red = Colour.objects.create(name='red') multicolor_item = ColourfulItem.objects.create() multicolor_item.colours.add(blue, red) red_item = ColourfulItem.objects.create() red_item.colours.add(red) class ColorModelChoiceField(forms.ModelChoiceField): def label_from_instance(self, obj): return ', '.join(c.name for c in obj.colours.all()) field = ColorModelChoiceField(ColourfulItem.objects.prefetch_related('colours')) with self.assertNumQueries(4): # would be 5 if prefetch is ignored self.assertEqual(tuple(field.choices), ( ('', '---------'), (multicolor_item.pk, 'blue, red'), (red_item.pk, 'red'), )) def test_foreignkeys_which_use_to_field(self): apple = Inventory.objects.create(barcode=86, name='Apple') Inventory.objects.create(barcode=22, name='Pear') Loading Loading
django/forms/models.py +3 −1 Original line number Diff line number Diff line Loading @@ -1102,7 +1102,9 @@ class ModelChoiceIterator(object): def __iter__(self): if self.field.empty_label is not None: yield ("", self.field.empty_label) for obj in self.queryset.iterator(): # Can't use iterator() when queryset uses prefetch_related() method = 'all' if self.queryset._prefetch_related_lookups else 'iterator' for obj in getattr(self.queryset, method)(): yield self.choice(obj) def __len__(self): Loading
docs/releases/1.8.6.txt +2 −1 Original line number Diff line number Diff line Loading @@ -9,4 +9,5 @@ Django 1.8.6 fixes several bugs in 1.8.5. Bugfixes ======== * ... * Fixed a regression causing ``ModelChoiceField`` to ignore ``prefetch_related()`` on its queryset (:ticket:`25496`).
tests/model_forms/tests.py +23 −0 Original line number Diff line number Diff line Loading @@ -2285,6 +2285,29 @@ class OtherModelFormTests(TestCase): with self.assertRaises(ValidationError): f.fields['status'].clean('z') def test_prefetch_related_queryset(self): """ ModelChoiceField should respect a prefetch_related() on its queryset. """ blue = Colour.objects.create(name='blue') red = Colour.objects.create(name='red') multicolor_item = ColourfulItem.objects.create() multicolor_item.colours.add(blue, red) red_item = ColourfulItem.objects.create() red_item.colours.add(red) class ColorModelChoiceField(forms.ModelChoiceField): def label_from_instance(self, obj): return ', '.join(c.name for c in obj.colours.all()) field = ColorModelChoiceField(ColourfulItem.objects.prefetch_related('colours')) with self.assertNumQueries(4): # would be 5 if prefetch is ignored self.assertEqual(tuple(field.choices), ( ('', '---------'), (multicolor_item.pk, 'blue, red'), (red_item.pk, 'red'), )) def test_foreignkeys_which_use_to_field(self): apple = Inventory.objects.create(barcode=86, name='Apple') Inventory.objects.create(barcode=22, name='Pear') Loading