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)
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.
- [Django]-Difference between Django's filter() and get() methods
- [Django]-In Django 1.4, do Form.has_changed() and Form.changed_data, which are undocumented, work as expected?
- [Django]-Auto-reloading of code changes with Django development in Docker with Gunicorn
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.
- [Django]-How do I add a "class" to a ChoiceField in Django?
- [Django]-How to use Python type hints with Django QuerySet?
- [Django]-JSON Serializing Django Models with simplejson
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:
-
Add
'django.forms'
to yourINSTALLED_APPS
; -
Add
FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
to yoursettings.py.
This all seems harder than it should be, but that’s frameworks. Good luck.
- [Django]-Django REST Framework: adding additional field to ModelSerializer
- [Django]-How to configure where to redirect after a log out in Django?
- [Django]-How do I use a dictionary to update fields in Django models?