mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[1.11.x] Fixed #27758 -- Reallowed AdvancedModelIterator pattern after template widget rendering.
Backport of 6d8979f4c2 from master
			
			
This commit is contained in:
		| @@ -569,8 +569,6 @@ class ChoiceWidget(Widget): | |||||||
|         for option_value, option_label in chain(self.choices): |         for option_value, option_label in chain(self.choices): | ||||||
|             if option_value is None: |             if option_value is None: | ||||||
|                 option_value = '' |                 option_value = '' | ||||||
|             else: |  | ||||||
|                 option_value = force_text(option_value) |  | ||||||
|  |  | ||||||
|             if isinstance(option_label, (list, tuple)): |             if isinstance(option_label, (list, tuple)): | ||||||
|                 index = groups[-1][2] + 1 |                 index = groups[-1][2] + 1 | ||||||
| @@ -586,7 +584,7 @@ class ChoiceWidget(Widget): | |||||||
|  |  | ||||||
|             for subvalue, sublabel in choices: |             for subvalue, sublabel in choices: | ||||||
|                 selected = ( |                 selected = ( | ||||||
|                     subvalue in value and |                     force_text(subvalue) in value and | ||||||
|                     (has_selected is False or self.allow_multiple_selected) |                     (has_selected is False or self.allow_multiple_selected) | ||||||
|                 ) |                 ) | ||||||
|                 if selected is True and has_selected is False: |                 if selected is True and has_selected is False: | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ from django.forms.models import ( | |||||||
|     ModelChoiceIterator, ModelFormMetaclass, construct_instance, |     ModelChoiceIterator, ModelFormMetaclass, construct_instance, | ||||||
|     fields_for_model, model_to_dict, modelform_factory, |     fields_for_model, model_to_dict, modelform_factory, | ||||||
| ) | ) | ||||||
|  | from django.forms.widgets import CheckboxSelectMultiple | ||||||
| from django.template import Context, Template | from django.template import Context, Template | ||||||
| from django.test import SimpleTestCase, TestCase, skipUnlessDBFeature | from django.test import SimpleTestCase, TestCase, skipUnlessDBFeature | ||||||
| from django.utils import six | from django.utils import six | ||||||
| @@ -1708,6 +1709,44 @@ class ModelChoiceFieldTests(TestCase): | |||||||
|         field = CustomModelChoiceField(Category.objects.all()) |         field = CustomModelChoiceField(Category.objects.all()) | ||||||
|         self.assertIsInstance(field.choices, CustomModelChoiceIterator) |         self.assertIsInstance(field.choices, CustomModelChoiceIterator) | ||||||
|  |  | ||||||
|  |     def test_modelchoicefield_iterator_pass_model_to_widget(self): | ||||||
|  |         class CustomModelChoiceValue: | ||||||
|  |             def __init__(self, value, obj): | ||||||
|  |                 self.value = value | ||||||
|  |                 self.obj = obj | ||||||
|  |  | ||||||
|  |             def __str__(self): | ||||||
|  |                 return str(self.value) | ||||||
|  |  | ||||||
|  |         class CustomModelChoiceIterator(ModelChoiceIterator): | ||||||
|  |             def choice(self, obj): | ||||||
|  |                 value, label = super(CustomModelChoiceIterator, self).choice(obj) | ||||||
|  |                 return CustomModelChoiceValue(value, obj), label | ||||||
|  |  | ||||||
|  |         class CustomCheckboxSelectMultiple(CheckboxSelectMultiple): | ||||||
|  |             def create_option(self, name, value, label, selected, index, subindex=None, attrs=None): | ||||||
|  |                 option = super(CustomCheckboxSelectMultiple, self).create_option( | ||||||
|  |                     name, value, label, selected, index, subindex=None, attrs=None, | ||||||
|  |                 ) | ||||||
|  |                 # Modify the HTML based on the object being rendered. | ||||||
|  |                 c = value.obj | ||||||
|  |                 option['attrs']['data-slug'] = c.slug | ||||||
|  |                 return option | ||||||
|  |  | ||||||
|  |         class CustomModelMultipleChoiceField(forms.ModelMultipleChoiceField): | ||||||
|  |             iterator = CustomModelChoiceIterator | ||||||
|  |             widget = CustomCheckboxSelectMultiple | ||||||
|  |  | ||||||
|  |         field = CustomModelMultipleChoiceField(Category.objects.all()) | ||||||
|  |         self.assertHTMLEqual( | ||||||
|  |             field.widget.render('name', []), | ||||||
|  |             '''<ul> | ||||||
|  | <li><label><input type="checkbox" name="name" value="%d" data-slug="entertainment" />Entertainment</label></li> | ||||||
|  | <li><label><input type="checkbox" name="name" value="%d" data-slug="its-test" />It's a test</label></li> | ||||||
|  | <li><label><input type="checkbox" name="name" value="%d" data-slug="third-test" />Third</label></li> | ||||||
|  | </ul>''' % (self.c1.pk, self.c2.pk, self.c3.pk), | ||||||
|  |         ) | ||||||
|  |  | ||||||
|     def test_modelchoicefield_num_queries(self): |     def test_modelchoicefield_num_queries(self): | ||||||
|         """ |         """ | ||||||
|         Widgets that render multiple subwidgets shouldn't make more than one |         Widgets that render multiple subwidgets shouldn't make more than one | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user