Add render method to ThemableCheckboxSelectMultiple

Django 1.11+ doesn't have RenderMixin class for widgets, so we have to
implement render method for ThemableCheckboxSelectMultiple to get it
rendered in a correct way with all supported Django versions until we
find a better solution for our widgets implementation.

Change-Id: I656afb162e130f2b77853368945b74330bedf747
Closes-Bug: #1715066
This commit is contained in:
Ivan Kolodyazhny 2017-09-26 17:26:45 +03:00 committed by Akihiro Motoki
parent 9adb636437
commit c13d6da80e
2 changed files with 22 additions and 40 deletions

View File

@ -527,10 +527,14 @@ class ThemableCheckboxChoiceInput(ChoiceInput):
def __init__(self, *args, **kwargs):
super(ThemableCheckboxChoiceInput, self).__init__(*args, **kwargs)
self.value = set(force_text(v) for v in self.value)
# NOTE(e0ne): Django sets default value to None
if self.value:
self.value = set(force_text(v) for v in self.value)
def is_checked(self):
return self.choice_value in self.value
if self.value:
return self.choice_value in self.value
return False
def render(self, name=None, value=None, attrs=None, choices=()):
if self.id_for_label:
@ -545,43 +549,23 @@ class ThemableCheckboxChoiceInput(ChoiceInput):
)
# NOTE(adriant): CheckboxFieldRenderer was removed in Django 1.11 so
# has been moved here until we redo how we handle widgets.
@html.html_safe
@python_2_unicode_compatible
class CheckboxFieldRenderer(object):
"""CheckboxFieldRenderer class from django 1.10.7 codebase
An object used by RadioSelect to enable customization of radio widgets.
"""
choice_input_class = None
class ThemableCheckboxSelectMultiple(widgets.CheckboxSelectMultiple):
choice_input_class = ThemableCheckboxChoiceInput
_empty_value = []
outer_html = '<ul{id_attr}>{content}</ul>'
inner_html = '<li>{choice_value}{sub_widgets}</li>'
def __init__(self, name, value, attrs, choices):
self.name = name
self.value = value
self.attrs = attrs
self.choices = choices
def __getitem__(self, idx):
return list(self)[idx]
def __iter__(self):
for idx, choice in enumerate(self.choices):
yield self.choice_input_class(
self.name, self.value, self.attrs.copy(), choice, idx)
def __str__(self):
return self.render()
def render(self):
def render(self, name=None, value=None, attrs=None):
"""Outputs a <ul> for this set of choice fields.
If an id was given to the field, it is applied to the <ul> (each
item in the list will get an id of `$id_$i`).
"""
attrs = {} or attrs
self.attrs = attrs
self.name = name
self.value = value
id_ = self.attrs.get('id')
output = []
for i, choice in enumerate(self.choices):
@ -615,15 +599,6 @@ class CheckboxFieldRenderer(object):
)
class ThemableCheckboxFieldRenderer(CheckboxFieldRenderer):
choice_input_class = ThemableCheckboxChoiceInput
class ThemableCheckboxSelectMultiple(widgets.CheckboxSelectMultiple):
renderer = ThemableCheckboxFieldRenderer
_empty_value = []
class ExternalFileField(fields.FileField):
"""Special FileField to upload file to some external location.

View File

@ -715,6 +715,13 @@ class SetNetworkAction(workflows.Action):
def __init__(self, request, *args, **kwargs):
super(SetNetworkAction, self).__init__(request, *args, **kwargs)
# NOTE(e0ne): we don't need 'required attribute for networks
# checkboxes to be able to select only one network
# NOTE(e0ne): we need it for compatibility with different
# Django versions (prior to 1.11)
self.use_required_attribute = False
network_list = self.fields["network"].choices
if len(network_list) == 1:
self.fields['network'].initial = [network_list[0][0]]