﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
22950	Subclassing choice select widgets should be easier	Patrick Robertson <django@…>	nobody	"So say I want to change the HTML of a RadioSelect widget from using `<ul>` to something like:


{{{
<div>
<label>label</label>
<input>
</div>
}}}


It sounds pretty simple right? But it looks like I need all of this code, which still doesn't work:


{{{
class BSChoiceFieldRenderer(widgets.ChoiceFieldRenderer):
    def render(self):
        """"""
        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`).
        """"""
        id_ = self.attrs.get('id', None)
        start_tag = format_html('<div id=""{0}"">', id_) if id_ else '<div>'
        output = [start_tag]
        for i, choice in enumerate(self.choices):
            choice_value, choice_label = choice
            if isinstance(choice_label, (tuple, list)):
                attrs_plus = self.attrs.copy()
                if id_:
                    attrs_plus['id'] += '_{0}'.format(i)
                sub_ul_renderer = ChoiceFieldRenderer(name=self.name,
                                                      value=self.value,
                                                      attrs=attrs_plus,
                                                      choices=choice_label)
                sub_ul_renderer.choice_input_class = self.choice_input_class
                output.append(format_html('<div>{0}{1}</div>', choice_value,
                                          sub_ul_renderer.render()))
            else:
                w = self.choice_input_class(self.name, self.value,
                                            self.attrs.copy(), choice, i)
                output.append(format_html('<div>{0}</div>', force_text(w)))
        output.append('</div>')
        return mark_safe('\n'.join(output))
        
class BSRadioFieldRenderer(BSChoiceFieldRenderer):
    choice_input_class = widgets.RadioChoiceInput
    
# Subclass of the RadioSelect widget
class BSRadioSelect(widgets.RadioSelect):
    renderer = BSRadioFieldRenderer

...
forms.py

something = forms.ChoiceField(choices=choices, widget=BSRadioSelect())
}}}


If I try and put the `render()` method in the `BSRadioFieldRenderer` subclass (so as to avoid having to subclass `ChoiceFieldRenderer`) I get an error about NoneType not being callable.
With the code as it stands here, the widget isn't actually rendered, just escaped HTML is printed"	Cleanup/optimization	closed	Forms	dev	Normal	fixed			Accepted	1	0	0	0	0	0
