It seems very few people used it, but... I did. Here you can read:
Some undocumented classes in django.forms.widgets are removed: SubWidget RendererMixin, ChoiceFieldRenderer, RadioFieldRenderer, CheckboxFieldRenderer ChoiceInput, RadioChoiceInput, CheckboxChoiceInput
My source code is:
from django.forms.widgets import ChoiceFieldRenderer, RadioChoiceInput, \
    RendererMixin, Select
class BootstrapRadioFieldRenderer(ChoiceFieldRenderer):
    outer_html = '<span {id_attr}>{content}</span>'
    inner_html = '<div class="radio">{choice_value}{sub_widgets}</div>'
    choice_input_class = RadioChoiceInput
class BootstrapRadioSelect(RendererMixin, Select):
    renderer = BootstrapRadioFieldRenderer
    _empty_value = ''
I really dont know how to convert this to make it work with 1.11 and later: they say:
Use a custom widget template instead.
Well. How?
We used RadioFieldRenderer to add a description to each option. Your usecase may be far from it, but I hope it helps you to make the migration too.
This was the legacy code for Django <=1.10
class MyRadioFieldRenderer(forms.widgets.RadioFieldRenderer):
    def render(self):
        radios = []
        for w in self:
            radios.append(u"""<li class="%s">%s <span>%s</span></li>"""
                          % (w.choice_value, force_unicode(w), get_description(w)))
        return mark_safe(u'<ul>\n%s\n</ul>' % u'\n'.join(radios))
class MyRadioSelect(forms.RadioSelect):
    renderer = MyRadioFieldRenderer
And I replaced it with this for Django 1.11 utilizing custom template snippets and only adding the description to the template context.
from django.forms.widgets import RadioSelect
class MyRadioSelect(RadioSelect):
    template_name = 'myapp/multiple_input.html'
    option_template_name = 'myapp/input_option.html'
    def get_context(self, name, value, attrs):
        context = super(MyRadioSelect, self).get_context(name, value, attrs)
        for i in range(len(context['widget']['optgroups'][0][1])):
            value = context['widget']['optgroups'][0][1][i]['value']
            context['widget']['optgroups'][0][1][i]['attrs']['description'] = \
                get_description(value)
        return context
The for loop in this deep list is not pretty. Need to look at that again.
In the template snippet I can then render the description behind the options with <span>{{widget.attrs.description | safe}}</span>
The form remained the same:
class MyForm(forms.Form):
    order_method = ChoiceField(
        widget=MyRadioSelect,
        required=True)
Important: For Django to find your custom template snippets in the regular template folder add this to your settings:
FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
and django.forms to your INSTALLED_APPS
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With