mirror of
				https://github.com/django/django.git
				synced 2025-10-30 09:06:13 +00:00 
			
		
		
		
	[1.8.x] Fixed #25496 -- Made ModelChoiceField respect prefetch_related().
Backport of 6afa6818fc from master
			
			
This commit is contained in:
		| @@ -1092,15 +1092,17 @@ class ModelChoiceIterator(object): | ||||
|     def __iter__(self): | ||||
|         if self.field.empty_label is not None: | ||||
|             yield ("", self.field.empty_label) | ||||
|         method = 'all' if self.queryset._prefetch_related_lookups else 'iterator' | ||||
|         queryset = getattr(self.queryset, method) | ||||
|         if self.field.cache_choices: | ||||
|             if self.field.choice_cache is None: | ||||
|                 self.field.choice_cache = [ | ||||
|                     self.choice(obj) for obj in self.queryset.iterator() | ||||
|                     self.choice(obj) for obj in queryset() | ||||
|                 ] | ||||
|             for choice in self.field.choice_cache: | ||||
|                 yield choice | ||||
|         else: | ||||
|             for obj in self.queryset.iterator(): | ||||
|             for obj in queryset(): | ||||
|                 yield self.choice(obj) | ||||
|  | ||||
|     def __len__(self): | ||||
|   | ||||
| @@ -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`). | ||||
|   | ||||
| @@ -2203,6 +2203,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') | ||||
|   | ||||
		Reference in New Issue
	
	Block a user