Can't override forms.RadioSelect template

Hi all,

Recently, I have tried override the template of widgets by implementing existing Django widget classes and changing the template name. For the forms.Select widget this works fine, however I can’t get it to work for the forms.RadioSelect widget.

So the following code allows me to override the template:

class SearchableSelect(forms.Select):
    template_name = "shared/searchableselect.html"

However, when I try to change the forms.RadioSelect class like this:

class SearchableRadioSelect(forms.RadioSelect):
    template_name = "shared/searchableselect.html"

I get the original template and not my own template. Additionally, it seems like render() is not executed for the RadioSelect widget but is executed for the Select widget.

I am implementing the widgets into the forms as follows:

user = forms.ModelChoiceField(label = "User", queryset = get_user_model().objects.all(), widget = SearchableRadioSelect)

What am I doing wrong here?

Thanks in advance,

Finn

1 Like

I did some further testing with this and looked into the source code but I can’t find why overriding the template_name for the RadioSelect widget shouldn’t work.

On thing I tried is copying the RadioSelect class and rename it using the source code:

class MyRadioSelect(forms.widgets.ChoiceWidget):
    input_type = "radio"
    template_name = "django/forms/widgets/radio.html"
    option_template_name = "django/forms/widgets/radio_option.html"
    use_fieldset = True

    def id_for_label(self, id_, index=None):
        if index is None:
            return ""
        return super().id_for_label(id_, index)

And adding it the the form like this:

choice = forms.ChoiceField(label = "Choice Field", choices = (("1", "Option 1"),("2", "Option 2")), initial = "1", widget = MyRadioSelect)

This doesn’t result in a radio widget but the following widget:
image

I assume I am missing something in the way RadioSelect widgets are rendered, can someone point me in the right direction?

Let me know if you need more info

Need to see the code for these two templates.

These are the default django templates.

django/forms/widgets/radio.html

{% include "django/forms/widgets/multiple_input.html" %}

With multiple_input.html

{% with id=widget.attrs.id %}<div{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}>{% for group, options, index in widget.optgroups %}{% if group %}
  <div><label>{{ group }}</label>{% endif %}{% for option in options %}<div>
    {% include option.template_name with widget=option %}</div>{% endfor %}{% if group %}
  </div>{% endif %}{% endfor %}
</div>{% endwith %}

django/forms/widgets/radio_option.html

{% include "django/forms/widgets/input_option.html" %}

With input_option.html

{% if widget.wrap_label %}<label{% if widget.attrs.id %} for="{{ widget.attrs.id }}"{% endif %}>{% endif %}{% include "django/forms/widgets/input.html" %}{% if widget.wrap_label %} {{ widget.label }}</label>{% endif %}

More code can be found here: https://github.com/django/django/tree/main/django/forms/templates/django/forms

Thanks in advance!

I did test your MyRadioSelect widget with Django widget templates and some custom widget templates, and in both cases, its rendering correctly.

Custom widget template
custom_template

Django widget template
django_template

How are you rendering your form? Are you using any Custom Form Renderer?

I do not have my own form rendering, but I do use crispy (with the bootstrap 5 template package) to render the form. Could that cause the issue?

It could.

I know I encountered an issue with buttons in one project when trying to upgrade Bootstrap 4 to 5. (It also uses Crispy.) That issue is currently unresolved - we went back to Bootstrap 4 for now. I’ll be looking at that project/issue again in about a month.

You could try Bootstrap 4, just to see if it’s a Crispy/Bootstrap 5 issue.

Switching to Bootstrap 4, doesn’t solve the issue unfortunatly.