[1.11.x] Fixed #27758 -- Reallowed AdvancedModelIterator pattern after template widget rendering.

Backport of 6d8979f4c2 from master
This commit is contained in:
Jon Dufresne 2017-01-31 06:41:51 -08:00 committed by Tim Graham
parent e2b19e70c7
commit 52e9c1c8b7
2 changed files with 40 additions and 3 deletions

View File

@ -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:

View File

@ -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&#39;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