[Django]-How to render individual radio button choices in Django?

54đź‘Ť

âś…

Django 1.4+ allows you to iterate over the choices in a RadioSelect, along with the lines of

{% for choice in form.pc_type %}
  {{ choice.choice_label }}
  <span class="radio">{{ choice.tag }}</span>
{% endfor %}

I’m not sure if this change allows you to use the syntax you describe ({{ form.pc_type.0 }}) — if not, you could work around this limitation with the for loop above and a tag like {% if forloop.counter0 == 0 %}.

If you’re tied to Django < 1.4, you can either override the render() method as suggested or go with the slightly-more-verbose-but-less-complicated option of building up the form field yourself in the template:

 {% for choice in form.pc_type.field.choices %}
   <input name='{{ form.pc_type.name }}' 
     id='{{ form.pc_type.auto_id }}_{{ forloop.counter0 }}' type='radio' value='{{ choice.0 }}'
     {% if not form.is_bound %}{% ifequal form.pc_type.field.initial choice.0 %} checked='checked' {% endifequal %}
   {% else %}{% ifequal form.pc_type.data choice.0 %} checked='checked' {% endifequal %}{% endif %}/>
   <label for='{{ form.pc_type.auto_id }}_{{ forloop.counter0 }}'>{{ choice.1 }}</label>
 {% endfor %}

(choice.0 and choice.1 are the first and second items in your choices two-tuple)

👤supervacuo

6đź‘Ť

The rendering of the individual radio inputs is handled by the RadioSelect widget’s render method. If you want a different rendering, subclass RadioSelect, change the render method accordingly, and then use your subclass as the field’s widget.

👤Chris Pratt

4đź‘Ť

I think the simply looking at what’s available inside the for loop of a choice field will tell one what they need to know. For example, I needed the value to set a class surrounding the span of the option (for colors and such):

<div>
    {% for radio_input in form.role %}
        {# Skip the empty value #}
        {% if radio_input.choice_value %}
            <span class="user-level {{ radio_input.choice_value }}">{{ radio_input }}</span>
        {% endif %}
    {% endfor %}
</div>

There are several attributes as you can see that keep you from having to use the ordinal.

PyCharm Debugging Inside a Template

👤Freddie

3đź‘Ť

In Django 2.0+ you can subclass forms.RadioSelect and “simply” specify a template for rendering the radio fields:

class SlimRadioSelect(forms.RadioSelect):
    template_name = 'includes/slim_radio.html'

where slim_radio.html contains a revised version of the combined template_name and option_template_name used by the default RadioSelect widget.

Note, the default RadioSelect widget template is low-level rendering and consists of heavily layered templates: include, conditional and loop logic tags abound.

You’ll know you’ve arrived when you’re digging around in packages/django/forms/templates/django/forms/widgets/input.html to get what you need.

One other oddity for overriding the default widget’s template is that you must invoke the TemplatesSetting renderer or your subclass won’t be able to find slim_radio.html in your project’s normally accessible template paths.

To override RadioSelect’s local-only template path lookup:

  1. Add 'django.forms' to your INSTALLED_APPS;

  2. Add FORM_RENDERER = 'django.forms.renderers.TemplatesSetting' to your settings.py.

This all seems harder than it should be, but that’s frameworks. Good luck.

👤Rob

Leave a comment